key 在 diff 中的作用
我们知道,Vue diff 算法的目的是对比虚拟 DOM 找出更新前与更新后的差异,通过只更新差异点来尽可能地减少对真实 DOM 的操作,从而提高性能。
在这个过程中复用节点是一个重要话题,如何找到能够复用的节点是 diff 算法中的一个重要的步骤,找到的能复用的节点越多也就代表着我们能尽可能少地去操作真实 DOM。
然而有时候我们并不能很好地识别哪些元素可以被复用,一个最经典的例子:
更新前
<div class='1'>1</div>
<div class='2'>2</div>
<div class='3'>3</div>
更新后
<div class='1'>1</div>
<div class='3'>3</div>
<div class='2'>2</div>
上面例子中,更新前、更新后的节点仅仅只是改变了顺序,其他都没有变化,最好的结果应该是直接通过移动 DOM 来更新。而实际在对比时,我们却发现不了这一点。我们只能将新、旧的三个元素逐个对比,然后更新其内容。
如果我们让开发人员给列表中每个元素添加一个 key 标识,那么上面例子如下:
更新前
<div key='1' class='1'>1</div>
<div key='2' class='2'>2</div>
<div key='3' class='3'>3</div>
更新后
<div key='1' class='1'>1</div>
<div key='3' class='3'>3</div>
<div key='2' class='2'>2</div>
这样一来,在 diff 时,我们就可以通过 key 来尝试在老的节点中找到可复用 DOM,从而实现 DOM 复用。
总结
Vue DIff 中的 key 是为了标识列表中的元素,这个 key 值在渲染前后不能变化,且在同级是唯一。这样 Vue 就可以根据 key 值在老的节点中寻找是否由可复用节点,从而尽可能地多复用真实 DOM,减少真实 DOM 操作,提升应用性能。