Svelte中点击{#each}块生成元素时如何获取对应DOM引用?
在Svelte的
{#each}循环中点击元素时获取对应DOM元素的方法 我正在用Svelte的{#each}功能响应式加载元素,代码如下:
{#each $items as item} <div> <Button on:click={someFunction}>{item.text}</Button> <!-- 一个转发自身on:click事件的组件 --> </div> {/each}
我希望点击生成的元素触发someFunction时,能获取到对应的实际DOM元素。我知道可以通过传递索引获取数组里的特定项,但那只能拿到数组项,不是唯一的DOM元素引用,该怎么实现?
我已经试过这些方法:
on:click={() => someFunction(this)}→ 返回undefinedon:click={(el) => someFunction(el)}→ 返回undefinedon:click={(e) => someFunction(e)}→ 用e.target能拿到点击的按钮,但得通过.parentElement获取外层div,这好像不是Svelte的最佳实践on:click={someFunction}配合bind:this={anItem}→ 只能拿到{#each}块里最后生成的元素
正确实现方法
方法1:给每个循环项绑定DOM引用到数组中
修改数组结构,给每个item添加存储DOM引用的属性,再通过bind:this绑定到对应元素:
<script> let items = $items.map(item => ({...item, domRef: null})); function someFunction(item) { // 此处item.domRef即为对应外层div的DOM引用 console.log(item.domRef); } </script> {#each items as item} <div bind:this={item.domRef}> <Button on:click={() => someFunction(item)}>{item.text}</Button> </div> {/each}
方法2:利用事件的currentTarget结合组件事件转发
由于Button组件会转发点击事件,事件的currentTarget会指向触发事件的Button元素,若需要外层div,用closest比parentElement更鲁棒:
<script> function someFunction(e) { // 获取Button组件对应的DOM元素 const buttonEl = e.currentTarget; // 获取外层div const divEl = buttonEl.closest('div'); console.log(divEl); } </script> {#each $items as item} <div> <Button on:click={someFunction}>{item.text}</Button> </div> {/each}
方法3:使用bind:this配合循环索引
如果不想修改原数组,可以创建单独数组存储每个循环项的DOM引用:
<script> let domRefs = []; function someFunction(index) { const divEl = domRefs[index]; console.log(divEl); } </script> {#each $items as item, index} <div bind:this={domRefs[index]}> <Button on:click={() => someFunction(index)}>{item.text}</Button> </div> {/each}
说明
- 方法1最贴合Svelte响应式思路,直接将DOM引用与数组项关联,逻辑清晰
- 方法2无需修改数据结构,适合快速获取DOM,但要注意DOM结构变化时
closest的适用性 - 方法3适合原数组不可修改的场景,通过索引映射DOM引用
内容的提问来源于stack exchange,提问作者Grabbels
相关产品推荐
相关产品推荐

