vue中v-for 的key为什么不能绑定index

<div id="app">
    <el-button type="primary" @click="add">添加</el-button>
    <ul>
        <li v-for="(item,index) in list" :key="item.id">
            <span>{{ item.name }}</span>
            <input type="text" />
        </li>
    </ul>
</div>
const list = ref([
    { name:"张三" , id:123 },
    { name:"李四" , id:456 },
])

function add(){
    list.value.unshift({ name:"王五" , id:789 })
}


1:首先,页面绑定的key为index的情况下,点击添加页面是没有问题的,但是当在对应的输入框输入数据的时候,会导致新增的元素会改变,但对应的值不会改变,依然在第一个input框中

例:

(原)张三:测试张三

          李四:测试李四

(新)王五:测试张三

           张三:测试李四

           李四:

2:把key改为id就不存在这类的问题

原因:

export function isSameVNodeType(n1: VNode, n2: VNode): boolean {
    return n1.type === n2.type && n1.key === n2.key
}

n1和n2分别代表旧节点和新节点,更新的时候,先判断一下,旧节点的type和新节点的type是不是一样的,(type为tagname,(例如 ‘div’,‘span’)示例中tag为li),如果是一样的就继续判断一下key是否一样,如果都是一样的,那么就用这个新节点去更新旧节点,如果不一样就接着找,找不到就代表着n2是新增的节点,直接插入就ok了。

如果key为id的情况下,根据上述规则直接找,发现key无重复,判断为新节点,则直接插入(其中input并不是响应式,所以不做比对)

反而key为index的情况下,根据上述情况,发现新增key->0有重复,就会默认覆盖旧节点,但因为input不是响应式,那么input就不会更新,依次往后,造成示例问题

### 解决方案 在 Vue3 中,`v-for` 循环内的元素可以通过 `v-model` 实现双向绑定。为了使列表项能够正确地进行双向绑定,通常会采用自定义事件的方式通知父组件更新数据。 #### 方法一:使用 `.sync` 修饰符与 `$emit` 当遍历数组并希望保持每一项的状态同步时,可以利用`.sync`修饰符来简化父子组件之间的通信过程: ```html <!-- 子组件 --> <template> <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"> </template> <script> export default { props: ['modelValue'], } </script> ``` ```html <!-- 父组件 --> <div v-for="(item, index) in items" :key="index"> <child-component :model-value.sync="items[index]" /> </div> ``` 这种方法允许子组件改变其属性值,并自动反映到父级的数据模型上[^1]。 #### 方法二:直接使用 `v-model` 对于更简洁的实现方式,在 Vue3 中可以直接使用 `v-model` 来代替上述方法中的`:modelValue` 和 `@input` 组合: ```html <!-- 子组件 --> <template> <input v-model="modelValue"/> </template> <script> import { defineComponent } from 'vue'; export default defineComponent({ name: "ChildComponent", props: { modelValue: String, }, }); </script> ``` ```html <!-- 父组件 --> <div v-for="(item, index) in items" :key="index"> <child-component v-model="items[index]" /> </div> ``` 这种方式不仅减少了模板代码量,还提高了可读性和维护性[^4]。 #### 注意事项 - 需要确保每次迭代都有唯一的键 (`:key`) ,这有助于提高性能以及防止潜在的问题。 - 对于复杂对象类型的双向绑定,则可能需要深拷贝以避免不必要的副作用[^5]。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值