Svelte {#each}迭代翻倍及绑定删除时报Cannot set properties of undefined错误
问题成因解析
1. {#each}迭代次数为预期值两倍的成因
- 最常见原因是当前使用SvelteKit或其他带服务端渲染(SSR)的开发环境:服务端会先执行一次{#each}逻辑生成初始DOM,客户端水合阶段会再执行一次渲染逻辑,最终呈现出迭代次数翻倍的现象,生产环境关闭SSR后该问题会自动消失。
- 次要原因是{#each}未指定唯一key值:Svelte默认使用数组索引作为迭代项的身份标识,当数组发生变更或绑定变量触发不必要重渲染时,内部diff逻辑可能误判生成重复节点。
2. 点击删除抛出"Cannot set properties of undefined"错误的成因
该错误由代码中的多处关联问题共同导致:
- 变量声明不符合响应式要求:你用
const声明了foodList,但后续通过foodList = foodList重新赋值触发响应式的操作违反了const不可重赋值的规则,会直接抛出赋值异常,连带影响后续绑定逻辑执行。 - 绑定目标错误:你在{#each}中解构了每个数组项的
elem字段,但bind:this却绑定了未声明的elems[index]变量,elems本身为undefined,绑定时尝试给undefined的对应索引属性赋值,直接触发报错。 - 事件传参错误:你写的
on:click={remove}会把点击事件对象作为参数传给remove函数,而非当前迭代项的索引,splice(事件对象, 1)执行逻辑完全不符合预期,会导致数组长度异常变更。 - 无唯一key导致绑定错乱:即使修复上述问题,未给{#each}指定唯一key的情况下,删除某一项后后续所有项的索引都会前移,Svelte更新
bind:this绑定时会尝试访问已经被删除的索引位置的变量,同样会抛出属性设置错误。
修复后可运行的参考代码
<script> // 改为let声明支持重赋值触发响应式 let foodList = [ // 新增id作为唯一key { id: 1, icon: '🍲', elem: null, }, { id: 2, icon: '🥫', elem: null, }, { id: 3, icon: '🍔', elem: null, }, ]; const remove = (index) => { foodList.splice(index, 1); foodList = foodList; }; </script> <!-- 新增key,绑定到当前项的elem属性,点击时传入index --> {#each foodList as {id, icon, elem}, index (id)} <div bind:this={elem} on:click={() => remove(index)} > {icon} </div> {/each}
内容的提问来源于stack exchange,提问作者Mero
相关产品推荐
相关产品推荐

