从实际的案例发现到在使用 v-for 时,将 key 值写成了 index,出现的问题。与其使用 index 作为 key ,不如完全不写 key,因为他们的性能是一样。比如一个列表长度为 10,用 index 作为 key ,各 item 的 key 值依次就是 0-9, 然后 reverse() 一下,列表的的 key 还是 0-9。在依次 patch 这 10 个 item 的时候,sameVnode() 全部返回真(因为 tag 和 key 都一样)。再看另外一种情况,如果不写 key , 那这 10 个 item 的 key 全部是 undefined, 在 sameVnode() 也是全部返回真(因为 tag 相同,key 也相同:key 都是 undefined)。所以得出结论,如果使用 index 作为 key,不如干脆不写 key 了,还能省下代码。
一、案例 bug 复现
父组件代码:
1 |
|
子组件代码:
1 |
|
当删除的时候,看上去是成功了,其实存在问题。加上排序也是存在问题。
将 v-for 里面的 key 换成 item 后,是正常的。
Vue 官网的描述:
当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
这个默认的模式是高效的,但是只适用于不依赖子组件装填或临时 DOM 状态的列表渲染输出。
二、总结
写列表渲染时,依赖子组件状态或者临时 DOM 状态的情况,如果存在删除、增加、排序这样的功能,不能将 index 作为 key 值。
这里还包括 diff 算法…(待添加)