正文
我们拿一个计数器举例,count
变量存在 store 中,我们用 count.set()
重置,用 count.subscribe()
订阅,用 count.update()
更新,一切看起来都很 OK,但实际上,如果想要更好的可维护性,这个 count 应该继续定义它的行为逻辑,也就是预定义好它的更新是怎样的、它的重置是怎样的。这样看起来似乎是在限制 count 的自由,但这种限制也意味着变动规则是可以把握的,而不是随处都有可能变动,也不是想怎么变就怎么变。
下面是一个没有使用自定义 store 的计数器功能:
// store.js import { writable } from 'svelte/store' export const count = writable(0) <!-- App.svelte --> <script> import { count } from "./store.js"; const increment = () => count.update((val) => val + 1); const decrement = () => count.update((val) => val - 1); const reset = () => count.set(0); </script> <h1>{$count}</h1> <button on:click={increment}> + </button> <button on:click={decrement}> - </button> <button on:click={reset}> reset </button>
功能逻辑放在特定组件里面,如果其他组件要用,那还得继续写。这其实就很冗余了,而且这些增加、减少、重置的逻辑应该是通用的,就算不通用,判断逻辑也应该写在一起,而不是分散在不同的组件里面。下面是使用自定义 store 后的效果。
// store.js import { writable } from 'svelte/store' export const count = createCount(0) function createCount(defaultVal) { const { subscribe, set, update } = writable(defaultVal) return { subscribe, // 形成 store 的必要条件 increment() { update(val => val + 1) }, decrement() { update(val => val - 1) }, reset() { set(0) }, } } <!-- App.svelte --> <script> import { count } from "./store.js"; </script> <h1>{$count}</h1> <button on:click={count.increment}> + </button> <button on:click={count.decrement}> - </button> <button on:click={count.reset}> reset </button>
这样做了后,逻辑就被安放到了 store 中,且没有暴露 set 和 update 给外界,意味着这两个方法是被保护起来了,因此增加、减少、重置的逻辑就这样统一做了定义。
注意
只要一个对象正确的使用 subscribe ,它就是可以称之为 store,因此上面自定义 store 中总是需要抛出 subscribe 方法。