<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就不会更新,依次往后,造成示例问题