v-for 时用index当做key unshift(1)整个列表重新渲染
v-for 时用index当做key unshift(1)整个列表重新渲染
旧的 新的
<ul> <ul>
<li key="0">a</li> <li key="0">新的</li>
<li key="1">b</li> <li key="1">a</li>
<li key="2">c</li> <li key="2">b</li>
<li key="3">c</li>
</ul> </ul>
list: ['a', 'b', 'c'];
// 往最前面加一项 unshift()
list: ['新的', 'a', 'b', 'c'];
按道理来说应该只会加一个li
进去,打开控制台却发现四个列表都在闪烁。
问题就出在源码里sameVnode
方法里
function sameVnode (a, b) {
return (a.key === b.key && a.asyncFactory === b.asyncFactory && (
(
a.tag === b.tag && a.isComment === b.isComment && isDef(a.data) === isDef(b.data) && sameInputType(a, b)
) || (isTrue(a.isAsyncPlaceholder) && isUndef(b.asyncFactory.error)
)
)
)
}
- 在patch时,Vue认为这两个
<li key="0">a</li>
和<li key="0">新的</li>
节点是相似的,key, tag, data也存在
然后进入patchVnode
去更新里面的文本。
- 剩下的节点由于
index
的改变, 形成了错位, 都会调用patchVnode
去更新里面的文本。
<li key="1">b</li> ---> <li key="1">a</li>
<li key="2">c</li> ---> <li key="2">b</li>
- 剩下最后的
<li key="3">c</li>
没有相对应的index
变成了新增
如何解决:
将 key
变成唯一的, 其他三个节点经过sameVnode
和patchVnode
比较 发现节点没有变,既不会重新渲染
而新加的节点,会在被添加进去