提升 Svelte stores 性能的 3 个技巧
Svelte stores
系统是一个优雅但低级的完整状态管理系统的实现。 存储本身并不是很复杂,Svelte 中响应式全局状态背后的大部分“魔法”都是由 Svelte 内部的响应式模型实现的。
您实际上不必使用从 svelte/store
导出的 store
来获取响应式全局状态。 只要您有一个遵循 Store 规范的object/class ,Svelte 就会将其识别为一个store
并使用它来执行 UI 更新。
如果它长得像鸭子,游得像鸭子,叫起来像鸭子,
那么它可能是一只鸭子。
知道了这一点,我们可以期望 Svelte 回声系统能够获得处理复杂全局状态的可扩展、复杂和高性能的实现。 我们甚至不必编写一行 Svelte 代码来创建它,只要它遵循规范即可!
如果您希望我讨论在 Svelte 中创建全局状态的可扩展模式,请告诉我! 现在,我们将保持简单,并查看一些可以应用于 Svelte 提供的默认存储的概念。
1:拆分你的stores
Svelte 在“当你的应用程序状态发生变化时以外科手术式
的方式更新 DOM”方面做得非常出色,但这并不是黑魔法。
假设您有一个 store
使用以下设置:
1 |
|
你可能认会这样做…
1 |
|
…只会触发监听 darkmode
属性的组件的更新,但事实是 Svelte
无法知道 darkmode
属性或 authenticated
属性是否已更新。 如果您查看 Svelte 如何“在后台”(使用普通 API)执行此更新,这将变得更容易掌握:
1 |
|
请注意,返回的是整个对象,因此 Svelte
只能知道此 store
中的某些内容已更新。 因此,必须检查所有订阅 store
的 components
以确定它们的任何状态是否已更改。
因此,第一个性能提示是将 stores
拆分为更小的 stores
,只保留经常在同一存储中一起使用的数据:
1 |
|
使用此设置,更新 darkmode
属性只会触发订阅此 store
的 components
的更新。
2: 使用 derived(派生) stores
假设您有一个包含多个项目的结帐购物车,并且您想根据结帐列表的状态更改购物车图标的外观。
看代码。
1 |
|
这个实现没有错,但我们可以做得更好! 当它们依赖的数据被更新时,反应性变量会被重新计算。 因此,如果出现以下情况,将重新计算 isEmpty 变量:
- 用户添加第一项
- 用户添加第二项
- 用户添加第三项
- 用户删除第三项
请注意,对于我们的用例,4 次重新计算中的 3 次是不必要的,因为我们只想知道购物车是否为空! 这就是派生商店出现的地方。 只有在前一个值和新值不相等时,存储才会触发更新,这意味着如果值从 false 更新为 false,则不会发生任何事情。 请注意,这主要适用于派生值是原始值的情况,因为更改是由严格的相等检查确定的。
因此,以下设置将在相同场景中减少 75% 的更新:
1 |
|
3:批量更新state(状态)
当您更新 store
时,Svelte
会执行以下操作:
运行 store
更新方法
将 update 方法返回的值设置为新的 store
值
使用新的 store
值调用订阅者
这种方法没有任何问题,但让我们看一下以下场景:
你有 10 个组件,每个组件都监听一些全局状态。 你向服务器询问一些数据,作为回报,你得到一个包含 100 个项目的数组。 你现在可以做两件事:
- 循环遍历数组并添加每个项目
- 添加整个数组
可能不是那么明显,但是第一种方法会触发 1000 次更新(10 个组件 * 100 次更新调用),而第二种方法只会触发 10 次更新(10 个组件 * 1 次更新调用)
因此,不要执行以下操作
1 |
|
你应该一直这样做:
1 |
|
如果我只能选择一种优化,我会选择这个。 我研究了一个问题,即进行这种单一优化将性能时间从 30 多秒减少到 400 毫秒左右。
原英文链接:https://www.mathiaspicker.com/posts/3-tips-for-upgrading-the-performance-of-your-svelte-stores