Svelte 访问子组件脚本标记中的存储变量
Svelte access a store variable in child component script tag
我有一个 Svelte & Sapper 应用程序,我在其中使用 Svelte 可写存储来设置一个具有初始空白字符串值的变量:
import { writable } from 'svelte/store';
export let dbLeaveYear = writable('');
在我的 Index.svelte
文件中,我正在导入它,然后计算出这个变量的值并进行设置(我在 ```[=37= 的 onMount
函数中执行此操作] 如果这是相关的):
<script>
import {dbLeaveYear} from "../stores/store.js"
function getCurrentLeaveYear() {
const today = new Date();
const currYear = today.getFullYear();
const twoDigitYear = currYear.toString().slice(-2);
const cutoffDate = `${twoDigitYear}-04-01`
const result = compareAsc(today, new Date(cutoffDate));
if (result === -1) {
$dbLeaveYear = `${parseInt(twoDigitYear, 10) - 1}${twoDigitYear}`;
} else {
$dbLeaveYear = `${twoDigitYear}${parseInt(twoDigitYear, 10) + 1}`;
}
}
onMount(() => {
getCurrentLeaveYear();
});
</script>
我在 Index.svelte
中呈现了一个子组件
<Calendar />
在 Calendar 子组件中,我正在导入变量并尝试访问它以对其执行转换,但我收到错误消息,它仍然是空白的 - 它似乎没有从 Index.svelte
:
<script>
import {dbLeaveYear} from "../stores/store.js"
const calStart = $dbLeaveYear.slice(0, 2)
</script>
但是,如果我在具有 <p>{$dbLeaveYear}</p>
的同一日历子组件中使用 HTML 元素中的值,它会填充 Index.svelte
.[=23 中的计算值=]
如何访问子组件的 <script>
标签内的 store 变量?这可能吗?我试过在 onMount
中赋值,我试过在一个函数中赋值 - 似乎没有任何效果,它总是说 $dbLeaveYear
是一个空字符串。
我需要这个值是动态的,因为休假年份值可以改变。
在深入研究您的问题之前,请允许我说您不应该直接改变存储变量,而应该使用提供的设置或更新方法。这避免了难以调试的错误:
if (result === -1) {
dbLeaveYear.set(() => `${parseInt(twoDigitYear, 10) - 1}${twoDigitYear}`);
} else {
dbLeaveYear.set(`${twoDigitYear}${parseInt(twoDigitYear, 10) + 1}`);
}
除此之外,问题似乎是您的 auto-subscribe 商店不适合您的用例。您需要为此使用订阅 属性:
<script>
import { dbLeaveYear } from "../stores/store.js"
import { onDestroy, onMount } from "svelte"
let yearValue;
// Needed to avoid memory leaks
let unsubscribe
onMount(() => {
unsubscribe = dbLeaveYear.subscribe(value => yearValue = value.slice(0, 2));
})
onDestroy(unsubscribe);
</script>
可能导致您遇到问题的另一件事是竞争条件。所以当子渲染时,父组件的更新还没有完成。然后你需要在渲染子组件中添加完整性检查。
这里的答案是 Sapper 预加载和从商店导出功能的能力的结合。
在 store.js
中导出您想要的变量的可写存储,以及一个计算值和设置可写存储的函数:
export let dbLeaveYear = writable('');
export function getCurrentLeaveYear() {
const today = new Date();
const currYear = today.getFullYear();
const twoDigitYear = currYear.toString().slice(-2);
const cutoffDate = `${twoDigitYear}-04-01`
const result = compareAsc(today, new Date(cutoffDate));
if (result === -1) {
dbLeaveYear.set(`${parseInt(twoDigitYear, 10) - 1}${twoDigitYear}`);
} else {
dbLeaveYear.set(`${twoDigitYear}${parseInt(twoDigitYear, 10) + 1}`);
}
}
在顶级 .svelte
文件中,在 "module"
脚本标记内使用 Sapper 的 preload()
函数来调用将计算值并设置可写存储的函数:
<script context="module">
import {getCurrentLeaveYear} from '../stores/store'
export async function preload() {
getCurrentLeaveYear();
}
</script>
然后在组件 .svelte
文件中,您可以导入存储变量,因为它已被预加载,所以它将在 <script>
标签中可用:
<script>
import {dbLeaveYear} from '../stores/store'
$: startDate = `20${$dbLeaveYear.slice(0, 2)}`
$: endDate = `20${$dbLeaveYear.slice(-2)}`
</script>
我有一个 Svelte & Sapper 应用程序,我在其中使用 Svelte 可写存储来设置一个具有初始空白字符串值的变量:
import { writable } from 'svelte/store';
export let dbLeaveYear = writable('');
在我的 Index.svelte
文件中,我正在导入它,然后计算出这个变量的值并进行设置(我在 ```[=37= 的 onMount
函数中执行此操作] 如果这是相关的):
<script>
import {dbLeaveYear} from "../stores/store.js"
function getCurrentLeaveYear() {
const today = new Date();
const currYear = today.getFullYear();
const twoDigitYear = currYear.toString().slice(-2);
const cutoffDate = `${twoDigitYear}-04-01`
const result = compareAsc(today, new Date(cutoffDate));
if (result === -1) {
$dbLeaveYear = `${parseInt(twoDigitYear, 10) - 1}${twoDigitYear}`;
} else {
$dbLeaveYear = `${twoDigitYear}${parseInt(twoDigitYear, 10) + 1}`;
}
}
onMount(() => {
getCurrentLeaveYear();
});
</script>
我在 Index.svelte
<Calendar />
在 Calendar 子组件中,我正在导入变量并尝试访问它以对其执行转换,但我收到错误消息,它仍然是空白的 - 它似乎没有从 Index.svelte
:
<script>
import {dbLeaveYear} from "../stores/store.js"
const calStart = $dbLeaveYear.slice(0, 2)
</script>
但是,如果我在具有 <p>{$dbLeaveYear}</p>
的同一日历子组件中使用 HTML 元素中的值,它会填充 Index.svelte
.[=23 中的计算值=]
如何访问子组件的 <script>
标签内的 store 变量?这可能吗?我试过在 onMount
中赋值,我试过在一个函数中赋值 - 似乎没有任何效果,它总是说 $dbLeaveYear
是一个空字符串。
我需要这个值是动态的,因为休假年份值可以改变。
在深入研究您的问题之前,请允许我说您不应该直接改变存储变量,而应该使用提供的设置或更新方法。这避免了难以调试的错误:
if (result === -1) {
dbLeaveYear.set(() => `${parseInt(twoDigitYear, 10) - 1}${twoDigitYear}`);
} else {
dbLeaveYear.set(`${twoDigitYear}${parseInt(twoDigitYear, 10) + 1}`);
}
除此之外,问题似乎是您的 auto-subscribe 商店不适合您的用例。您需要为此使用订阅 属性:
<script>
import { dbLeaveYear } from "../stores/store.js"
import { onDestroy, onMount } from "svelte"
let yearValue;
// Needed to avoid memory leaks
let unsubscribe
onMount(() => {
unsubscribe = dbLeaveYear.subscribe(value => yearValue = value.slice(0, 2));
})
onDestroy(unsubscribe);
</script>
可能导致您遇到问题的另一件事是竞争条件。所以当子渲染时,父组件的更新还没有完成。然后你需要在渲染子组件中添加完整性检查。
这里的答案是 Sapper 预加载和从商店导出功能的能力的结合。
在 store.js
中导出您想要的变量的可写存储,以及一个计算值和设置可写存储的函数:
export let dbLeaveYear = writable('');
export function getCurrentLeaveYear() {
const today = new Date();
const currYear = today.getFullYear();
const twoDigitYear = currYear.toString().slice(-2);
const cutoffDate = `${twoDigitYear}-04-01`
const result = compareAsc(today, new Date(cutoffDate));
if (result === -1) {
dbLeaveYear.set(`${parseInt(twoDigitYear, 10) - 1}${twoDigitYear}`);
} else {
dbLeaveYear.set(`${twoDigitYear}${parseInt(twoDigitYear, 10) + 1}`);
}
}
在顶级 .svelte
文件中,在 "module"
脚本标记内使用 Sapper 的 preload()
函数来调用将计算值并设置可写存储的函数:
<script context="module">
import {getCurrentLeaveYear} from '../stores/store'
export async function preload() {
getCurrentLeaveYear();
}
</script>
然后在组件 .svelte
文件中,您可以导入存储变量,因为它已被预加载,所以它将在 <script>
标签中可用:
<script>
import {dbLeaveYear} from '../stores/store'
$: startDate = `20${$dbLeaveYear.slice(0, 2)}`
$: endDate = `20${$dbLeaveYear.slice(-2)}`
</script>