如何封装状态函数在Svelte像React钩子?



我正在尝试将状态控制函数从组件中提取到Svelte中的单个组件(或函数)中,以便重用和解耦,如React hook。

我尝试像下面这样封装计数器增量,但它不起作用。反应性丧失,计数也不会增加。我应该如何提取状态控制功能正确在苗条?

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>

在这种情况下,如果您希望重用不同的Svelte组件中的功能并将其封装在函数中,请将该函数写入常规JavaScript文件并使用store:

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>

不能在useIncrement.js中使用常规变量重赋值(x = y)的原因是,只有当重赋值发生在其自己的组件中时,Svelte才会在视图中反映变量的更新。您从未在App.svelte中为count赋新值,这就是为什么它在代码片段中不起作用的原因。此外,Svelte不会对常规JavaScript文件应用特殊逻辑。这就是为什么需要在store中包装计数器并订阅其更改的原因。

Docs on stores: https://svelte.dev/docs#svelte_store

最新更新