从vue源码角度分析key的做用

在文档中说到:html

  • key 的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes
  • 若是不使用 key,Vue 会使用一种最大限度减小动态元素而且尽量的尝试就地修改/复用相同类型元素的算法。
  • 而使用 key 时,它会基于 key 的变化从新排列元素顺序,而且会移除/销毁 key 不存在的元素。

在分析以前须要简单了解俩个概念 Vnode虚拟DOMvue

须要了解的俩个概念

Vnode

Vnode 全称为 Virtual Node, 即 虚拟节点 ,而它的本质就是一个JS对象node

以代码为例:web

<div class="text" style="font-size: 26px;color: pink">这是一段文本内容</div>
复制代码

// vue 会把 模板中的内容 转换为 vNode(对象)算法

const vNode = {
  type: 'div',
  props: {
    class: 'text',
    style: {
      'font-size': '26px',
      color: 'pink'
    },
  },
  children:'这是一段文本内容'
};
复制代码

虚拟DOM

文档中说到:api

  • 虚拟 DOM 是轻量级的 JavaScript 对象,由渲染函数建立。
  • 它包含三个参数:元素,具备数据、prop、attr 等的对象,以及一个数组。
  • 数组是咱们传递子级的地方,子级也具备全部这些参数,而后它们也能够具备子级,依此类推,直到咱们构建完整的元素树为止。

以代码为例:数组

<div>
  <h1>标题</h1>
  这是一段文本内容
  <!-- 这是注释 -->
</div>
复制代码

// 转换为虚拟DOMmarkdown

image.png

插入内容的案例

先看一个案例:当咱们点击按钮时会插入一个数字5进去:svg

image.png

在整个过程当中,咱们能够肯定的是vue在内部此次更新对于ul和button是不须要进行更新,须要更新的是li的列表。函数

在Vue中,对于相同父元素的子元素节点并不会从新渲染整个列表;由于对于列表中 一、二、三、4 它们都是没有变化的。在操做真实DOM的时候,咱们只须要在中间插入一个5的li便可。

那么Vue中对于列表的更新到底是如何操做的呢?

Vue事实上会对于有key和没有key会调用两个不一样的方法:

  1. 有key,那么就使用 patchKeyedChildren 方法;
  2. 没有key,那么久使用 patchUnkeyedChildren 方法;

Vue3源码对于Key的判断

image.png

没有key的操做状况下,vue源码的作法

在没有key的状况下,vue3源码是经过 patchUnkeyedChildren 方法来实现的

具体实现如图下:

第一步:遍历循环经过patch方法来作比较 image.png 第二步和第三步:判断新旧nodes的长度来进行对节点的删除或者新增 image.png

在有key的状况下,vue源码的作法

有key的状况下,vue对其操做有点复杂,可分为 5 个步骤。

具体以下图所示:

第一步:

image.png

第二步:

image.png

第三步:

image.png

第四步:

image.png

第五步:

image.png

总结

咱们能够发现,Vue在进行diff算法的时候,会尽可能利用咱们的key来进行优化操做,全部在没有key的状况下咱们的效率是很是低的。 在进行插入或者重置排序的时候,保持相同的key可让diff算法更加高效。

相关文章
相关标签/搜索