如何像React hook一样在Svelte中封装状态函数?

Joh*_*ton 1 javascript svelte

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

我尝试封装一个计数器增量如下,但它不起作用。反应性丧失并且计数不增加。我应该如何在 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>

Run Code Online (Sandbox Code Playgroud)

应用程序.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>

Run Code Online (Sandbox Code Playgroud)

dum*_*umm 6

在这种情况下,如果您想要重用不同 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;
}
Run Code Online (Sandbox Code Playgroud)

在这种特定情况下,可以通过使用可读存储并删除以下内容来简化代码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);
    };
  });
}
Run Code Online (Sandbox Code Playgroud)

应用程序.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>
Run Code Online (Sandbox Code Playgroud)

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

商店文档: https: //svelte.dev/docs#svelte_store