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

时间:2021-02-26 02:40:33

标签: javascript svelte

我正在尝试将状态控制功能从组件提取到 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>

1 个答案:

答案 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 文件应用特殊逻辑。这就是为什么您需要将计数器包装在商店中并订阅其更改。

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

相关问题