如何正确创建并遍历含多层嵌套对象的大型Svelte Store?
关于Svelte Writable Store嵌套更新与渲染的疑问解答
初始数据结构
你创建的三级嵌套Writable Store结构如下:
const top = writable([ { n: 'a', c: [ { n: 'j', g: [ { n: '1' }, { n: '2' }] }, { n: 'k' }, { n: 'l'}] }, { n: 'b', c: [ { n: 'q' }, { n: 'r', g: [ { n: '1' }, { n: '2' }] }, { n: 's'}] }, { n: 'c', c: [ { n: 'x' }, { n: 'y' }, { n: 'z', g: [ { n: '1' }, { n: '2' }] }] } ]);
当前更新逻辑(存在错误修正)
你处理网络事件的代码有几处逻辑问题,比如父节点遍历子节点应该用p.c.forEach而非p.forEach,found变量始终未置为true,且未遵循不可变更新原则,修正后的合理写法如下:
onNetworkEvent(({ parent, child, grandchild }) => { top.update(t => { return t.map(p => { if (p.n !== parent) return p; // 复制父节点,避免直接修改原对象 return { ...p, c: p.c.map(cItem => { if (cItem.n !== child) return cItem; // 复制子节点,追加新的孙节点 return { ...cItem, g: [...(cItem.g || []), { n: grandchild }] }; }) }; }); }); });
疑问1:遍历父节点找目标修改是否属于不良风格?
完全不算。你的总孙节点才几十个,遍历的性能开销可以忽略不计,这种写法逻辑直白、可读性强,在小规模数据场景下非常合适。
如果未来数据量大幅增长(比如成百上千个节点),可以提前维护一个映射表(比如Map<string, 子节点引用>)来直接定位目标,减少遍历次数,但目前完全没必要过度优化。
疑问2:重置整个store会导致全量重渲染吗?
Svelte会智能识别未变更的部分,不会触发全量重渲染。
- Svelte的
{#each}块会基于对象引用判断是否需要更新DOM:如果某个父节点/子节点的引用没有变化,对应的DOM不会被重新渲染,只有被修改的孙节点所在的DOM会更新。 - 建议给
{#each}加上唯一key来进一步优化渲染精准度,比如:
<div class="parent"> {#each $top as p (p.n)} <div class="child"> {#each p.c as cItem (cItem.n)} <div>{cItem.n}</div> {#each cItem.g || [] as gItem (gItem.n)} <div>{gItem.n}</div> {/each} {/each} </div> {/each} </div>
加上key后,Svelte能更精准地跟踪每个项的变化,避免因数组顺序变动导致的不必要渲染。
内容的提问来源于stack exchange,提问作者xrd
相关产品推荐
相关产品推荐

