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)
      )
    )
  )
}
  1. 在patch时,Vue认为这两个<li key="0">a</li><li key="0">新的</li> 节点是相似的,key, tag, data也存在

然后进入patchVnode去更新里面的文本。

  1. 剩下的节点由于index的改变, 形成了错位, 都会调用patchVnode去更新里面的文本。
 <li key="1">b</li>    --->    <li key="1">a</li>
 <li key="2">c</li>    --->    <li key="2">b</li>
  1. 剩下最后的 <li key="3">c</li> 没有相对应的index 变成了新增

如何解决:

key变成唯一的, 其他三个节点经过sameVnodepatchVnode 比较 发现节点没有变,既不会重新渲染

而新加的节点,会在被添加进去

posted @ 2021-09-23 15:09  古月大叔  阅读(228)  评论(0编辑  收藏  举报