自定义方法与响应式值的Svelte Store问题排查与修正
解决Svelte自定义Store中选中状态与统计值不响应更新的问题
问题场景
我在做一个Svelte组件,用来展示可加入选中集合的列表项,选中集合用自定义Store(selectionStore.js)管理。这个Store里写了add、remove、toggleSelection这些操作方法,还加了isSelected用来判断项是否选中,length用来统计选中数量。
但在RecordList.svelte和Record.svelte里用的时候发现,isSelected的结果和选中数量selectionLength都不跟着Store更新走——明明toggleSelection能正常改选中集合,可组件里的状态就是不变。
问题根源
自定义Store里直接定义的isSelected、length这类方法就是普通函数,不会触发Svelte的响应式追踪。当Store内部的选中集合变了之后,这些方法的返回值不会自动重新计算,组件自然感知不到变化。
解决办法
把isSelected和nbSelected(选中数量)改成基于原Store的derived派生Store,利用派生Store自动订阅原Store变化、自动重新计算的特性,实现响应式更新:
改造后的selectionStore.js
import { writable, derived } from 'svelte/store'; // 基础的选中集合Store const { subscribe, update } = writable(new Set()); // 派生Store:判断指定项是否选中 export const isSelected = derived( [subscribe], ($selected) => (itemId) => $selected.has(itemId) ); // 派生Store:统计选中数量 export const nbSelected = derived( [subscribe], ($selected) => $selected.size ); // 保留原有操作方法 export const toggleSelection = (itemId) => { update(selected => { const newSet = new Set(selected); newSet.has(itemId) ? newSet.delete(itemId) : newSet.add(itemId); return newSet; }); }; export const add = (itemId) => { update(selected => new Set([...selected, itemId])); }; export const remove = (itemId) => { update(selected => { const newSet = new Set(selected); newSet.delete(itemId); return newSet; }); };
组件使用示例
Record.svelte中判断选中状态:
<script> import { isSelected, toggleSelection } from './selectionStore.js'; export let item; </script> <div class:selected={$isSelected(item.id)} on:click={() => toggleSelection(item.id)} > {item.name} </div> <style> .selected { background: #f0f0f0; } </style>
RecordList.svelte中展示选中数量:
<script> import { nbSelected } from './selectionStore.js'; import Record from './Record.svelte'; export let items; </script> <p>已选中:{$nbSelected} 项</p> {#each items as item} <Record {item} /> {/each}
改成派生Store之后,只要原选中集合变化,isSelected和nbSelected就会自动重新计算,组件里的状态也能实时更新了。
内容的提问来源于stack exchange,提问作者Seglinglin
相关产品推荐
相关产品推荐

