深入理解Vue中的key与diff算法

2022/6/7 Vuediff算法

# v-for的key值

在v-for进行遍历时,通常会给元素和组件绑定一个key属性。

 <li v-for="(item,index) in movies" :key="item">{{item}}</li>
1

官方解释:

key属性主要是用在Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes。 如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法(diff算法)。 而使用key时,它会基于key值的变化重新排列元素顺序,并且会移除/销毁key不存在的元素。

# 什么是VNode?

VNode全称是Virtual Node,也就是虚拟节点。浏览器在渲染页面时,一个元素就是一个个真实DOM节点。无论是组件还是元素,在vue中表现出的就是一个个VNode。VNode的本质时=是一个js对象。template会先转换成VNode再转换成真实DOM。VNode的好处就是能跨平台。

# 什么是虚拟DOM?

如果不是只有一个简单的div,而是有一大堆元素,那么他们会形成一个VNode Tree。一般把这个树结构成为虚拟DOM。

# Vue中的 diff算法

初次渲染的时候,将VDOM渲染成真正的DOM然后插入到容器里面。 再需要更新的时候,把旧的VNode和新的VNode进行对比,最后得出哪里需要更新。

Vue中的对于有key和无key的两种对比算法:

# patchKeyedChildren 方法

在有key的情况下:

  1. 从头部开始,在while循环中对每个节点进行类型和key的比较,如果不相同就跳出循环
  2. 从尾部开始再次进行第一步的操作
  3. 如果旧节点遍历完了,依然有新节点,那么就是添加,会找到新节点的位置,使用null和新节点进行比较(表示一次挂载 mount),把新节点进行挂载。
  4. 如果上一步操作中,还剩余旧节点,那么就是卸载,会将旧节点移除掉(unmount)。
  5. 如果中间是无序的,那么就会尽可能的在旧节点中找到新的节点,会尽可能的在旧节点中利用,然后有多余的节点就进行移除,有新增的就进行挂载。

# patchUnkeyedChildren 方法

无key情况下,会对比新旧VNode节点的长度,使用最少的进行比较。从0的位置进行比较如果旧的节点数大于新的节点数。就移除剩余的节点。否则就创建新的节点,再把新的节点挂载到VNode列表之上。最后完成所有节点的重新创建。

Last Updated: 2022/12/12下午11:51:23