在Svelte中进行组件间的跨组件状态管理
在Svelte中处理单个组件的状态非常简单。
但是如何在组件之间传递状态呢?
使用props传递状态
第一种策略是其他UI框架常见的策略,即使用props传递状态,将状态上升。
当一个组件需要与另一个组件共享数据时,可以将状态上升到组件树中的共同父级。
状态需要通过props传递,直到到达需要此状态信息的所有组件。
这是使用props完成的,我认为这是最好的技术,因为它很简单。
有关props的更多信息,请参考Svelte Props教程。
Context API
有些情况下,props并不是一个实用的方法。也许两个组件在组件树中距离太远,我们必须将状态移动到顶层组件。
在这种情况下,可以使用另一种技术,称为context API,它非常适合让多个组件与后代组件进行通信,而无需传递props。
context API由svelte
软件包提供的两个函数提供:getContext
和setContext
。
您可以设置与键关联的上下文对象:
1 | <script> |
在另一个组件中,您可以使用getContext来检索分配给键的对象:
1 | <script> |
您只能在使用setContext的组件或其子代之一中使用getContext检索键。
如果要让两个位于两个不同组件树中的组件进行通信,那么我们还有另外一个工具:stores。
使用Svelte stores
当组件需要相互通信而无需传递太多props时,Svelte stores是一种非常好的工具来处理应用程序的状态。
首先,您必须从svelte/store
中导入可写的writable
:
1 | import { writable } from 'svelte/store' |
然后使用writable()
函数创建一个存储变量,将默认值作为第一个参数传递:
1 | const username = writable('Guest') |
这可以放在一个单独的文件中,您可以将其导入多个组件中,例如称为store.js
的文件中(它不是一个组件,因此可以是.js
文件而不是.svelte
):
1 | import { writable } from 'svelte/store' |
加载此文件的任何其他组件现在都可以访问存储:
1 | <script> |
现在可以使用set()
将此变量的值设置为新值,将新值作为第一个参数传递:
1 | username.set('new username') |
并且可以使用update()
函数进行更新。update()
与set()
的不同之处在于不仅仅将新值传递给它-您还可以运行一个回调函数,该回调函数将当前值作为其参数传递:
1 | const newUsername = 'new username!' |
在这里您可以添加更多逻辑:
1 | username.update(existing => { |
要一次性获取存储变量的值,可以使用svelte/store
导出的get()
函数:
1 | import { readable, get } from 'svelte/store' |
要创建一个响应式变量,使其在更改时更新,您可以在存储变量之前加上$
,例如$username
。使用它将使组件在存储的值更改时重新渲染。
Svelte认为
$
是一个保留值,并且会阻止您在与存储值无关的事物上使用它(可能会导致混淆),因此如果您习惯使用$
作为DOM引用的前缀,请不要在Svelte中使用。
另一个选择,如果您需要在变量更改时执行一些逻辑,则可以使用username
的subscribe()
方法:
1 | username.subscribe(newValue => { |
除了可写存储之外,Svelte还提供了两种特殊类型的存储:可读存储和派生存储。
Svelte可读存储
可读存储是特殊的,因为它们不能从外部更新-没有set()
或update()
方法。而是,在设置初始状态后,它们不能从外部修改。
官方的Svelte文档展示了一个使用定时器更新日期的有趣示例。我可以想到使用定时器从网络获取资源、执行API调用、从文件系统中获取数据(使用本地Node.js服务器)或任何其他可以自主设置的操作。
在这种情况下,我们使用readable()
而不是writable()
来初始化存储变量:
1 | import { readable } from 'svelte/store' |
您可以在默认值之后提供一个函数,该函数负责更新它。此函数接收set
函数以修改该值:
1 | <script> |
在这种情况下,我们在1秒后将值从0更新为1。
您还可以在此函数中设置间隔:
1 | import { readable, get } from 'svelte/store' |
您可以像这样在另一个组件中使用它:
1 | <script> |
Svelte的派生存储
派生存储允许您创建一个新的存储值,该值依赖于现有存储的值。
您可以使用derived()
函数来实现这一点,该函数由svelte/store
导出,其中第一个参数是现有存储的值,第二个参数是一个函数,该函数将该存储的值作为其第一个参数:
1 | import { writable, derived } from 'svelte/store' |
您可以像这样在另一个组件中使用它:
1 | <script> |
tags: [“svelte”, “state management”, “props”, “context API”, “stores”]