Svelte中Radio button绑定数组对象name的响应式问题求助
Svelte Radio绑定name属性同步问题修复
问题背景
数组中存放多个对象,用户需通过Radio按钮选择要使用的数组项,同时允许用户修改对象的name属性(obj.name)。选中值需要单独存储,且必须为选中对象的obj.name属性。
原始问题代码
<script> let selectedName = ""; let arr = []; let obj1 = {}; obj1.id = 1; obj1.name = "One"; let obj2 = {}; obj2.id = 2; obj2.name = "Two"; let obj3 = {}; obj3.id = 3; obj3.name = "Three"; arr.push(obj1, obj2, obj3); </script> <input type="text" bind:value={selectedName}/> <hr> {#each arr as row} <input type="radio" bind:group={selectedName} value={row.name}/> {row.id} <input type="text" bind:value={row.name}/> <br/> {/each}
异常表现
- 初始选中ID为2的选项,上方文本框同步显示
Two - 将ID为1的选项名称从
One修改为Uno,再选中ID为1的选项,上方文本框同步更新为Uno - 此时将ID为1的选项名称从
Uno修改为Ein,上方文本框无同步更新
原因说明
- Svelte的
bind:group绑定在单选框上时,仅会在单选框选中状态发生变化时同步绑定的selectedName值,后续单选框对应的value属性变更不会主动触发selectedName的更新 - 给单选框加
bind:value的修改方式会导致逻辑异常,是因为双向绑定value后,selectedName的变更会反向修改所有单选框的value值,直接打乱数组对象的name属性
修复方案
通过增加响应式同步逻辑实现选中项name变更时的自动同步,同时满足selectedName始终存储选中对象的name属性的要求,修复后代码如下:
<script> let selectedName = ""; // 新增:存储当前选中的行对象,用于跟踪name变化 let selectedRow = null; let arr = []; let obj1 = {}; obj1.id = 1; obj1.name = "One"; let obj2 = {}; obj2.id = 2; obj2.name = "Two"; let obj3 = {}; obj3.id = 3; obj3.name = "Three"; arr.push(obj1, obj2, obj3); // 响应式同步1:选中行变化时更新selectedName $: if (selectedRow) selectedName = selectedRow.name; // 响应式同步2:selectedName变化时匹配对应的选中行(兼容手动修改顶部输入框的场景) $: selectedRow = arr.find(row => row.name === selectedName) ?? null; </script> <input type="text" bind:value={selectedName}/> <hr> {#each arr as row} <!-- 单选框绑定选中行对象 --> <input type="radio" bind:group={selectedRow} value={row}/> {row.id} <input type="text" bind:value={row.name}/> <br/> {/each}
该方案下修改选中项的name时,响应式逻辑会自动同步更新selectedName,完全符合业务要求。
内容的提问来源于stack exchange,提问作者Krillegeddon
相关产品推荐
相关产品推荐

