我正在尝试将状态控制功能从组件提取到 Svelte 中的单个组件(或函数),以便重用和解耦,例如 React 钩子。
我尝试将计数器增量封装如下,但它不起作用。反应性丢失,计数不会增加。如何在 Svelte 中正确提取状态控制功能?
useIncrement.svelte
<script context="module">
import {onMount} from 'svelte';
function useIncrement(){
let count = 0;
onMount(() => {
const interval = setInterval(() => count++, 1000);
return () => {
clearInterval(interval);
};
});
console.log('toggling')
return count
}
export {
useIncrement
}
</script>
App.svelte
<script>
import { useIncrement } from './useToggle.svelte'
import {onMount} from 'svelte';
let count = useIncrement()
</script>
<div class="App">
<p>Page has been open for <code>{count}</code> seconds.</
</div>
答案 0 :(得分:4)
在这种情况下,您希望在不同的 Svelte 组件中重用功能并将其封装在一个函数中,请将该函数写入常规 JavaScript 文件并使用存储:
useIncrement.js
import { onMount } from 'svelte';
import { writable } from 'svelte/store';
export function useIncrement(){
let count = writable(0); // <- wrap count in a store
onMount(() => {
// instead of count++, use the store's update function:
const interval = setInterval(() => count.update(c => c + 1), 1000);
return () => {
clearInterval(interval);
};
});
return count;
}
在这种特定情况下,可以通过使用可读存储并删除 onMount
来简化代码:
useIncrement.js
import { readable } from 'svelte/store';
export function useIncrement() {
let count = 0;
return readable(count, set => {
const interval = setInterval(() => set(++count), 1000);
// Will be called on unsubscribe:
return () => {
clearInterval(interval);
};
});
}
App.svelte
<script>
import { useIncrement } from './useIncrement'
let count = useIncrement()
</script>
<div class="App">
<!-- subscribe to the store by prepending $ to the variable -->
<p>Page has been open for <code>{$count}</code> seconds.
</div>
您不能在 x = y
中使用常规变量重新分配 (useIncrement.js
) 的原因是,只有当重新分配发生在视图中时,Svelte 才会发挥其在视图中反映变量更新的魔力自己的组件。您永远不会为 count
中的 App.svelte
分配新值,这就是它在您的代码段中不起作用的原因。此外,Svelte 不会对常规 JavaScript 文件应用特殊逻辑。这就是为什么您需要将计数器包装在商店中并订阅其更改。