VDOM diff

VDOM

  • VDOM,JavaScript对象,即对真实DOM的描述;
  • 虚拟DOM创建页面性能:创建JavaScript对象的计算量 + 创建真实DOM的计算量;(第一步,创建JavaScript对象,即真实DOM的描述;第二步,递归地遍历虚拟DOM树并创建真实DOM;)
  • 虚拟DOM更新更新页面过程:1. 重新渲染JavaScript对象(虚拟DOM树);2. 比较新旧虚拟DOM Diff,找到变化的元素并更新它;


VDOM diff

  1. React diff 为了避免遍历节点的复杂度,只对比同一层的虚拟节点;
  • newDOM中的节点存在,oldDOM中不存在,那么就新增一个节点;
  • newDOM中的节点不存在,oldDOM中存在,那么就删除oldDOM中的节点;
  • newDOM和oldDOM中的节点都存在,对比是否是同一个节点,是同一个节点再比较子元素是否相同;
  • 两个节点都存在时,比较它们的子节点,若子节点是文本节点,更新子节点的文本为new节点的文本,如果子节点不是文本节点且不相同时,比如子节点顺序发生改变,React中使用的是下标递增的方式来判断节点的位置是否需要调整的,然后我们开始遍历newDOM,依次查询newDOM中的节点在oldDOM中的下标位置,并记录下来,如果新的下标小于之前保存的下标说明位置需要调整,调整到newDOM的前一个真实节点之后,如果不小于,则保持位置不用调整;

  1. vue2 diff
  • Vue将虚拟DOM和watcher相结合,每个组件都有自己对应的虚拟DOM,那么当组件内部的数据发生改变时,Vue是怎么样同步渲染页面的呢?
  • 当组件内部数据发生改变时,会触发数据的setter方法,进而通知到watcher对象,watcher会触发更新函数,通过render函数获取到新的虚拟DOM结构,然后将newDOM和oldDOM进行解析获取到最小变动,根据最小变动内容更新页面DOM。
  • newDOM中的节点存在,oldDOM中不存在,那么就新增一个节点;
  • newDOM中的节点不存在,oldDOM中存在,那么就删除oldDOM中的节点;
  • 新老节点相同时,并且子节点不同的情况,Vue中是如何处理的:
  • 首尾比对的diff算法;
  • 1--newDOM和oldDOM首位对比,相同,对比位置同时向后移动,节点位置不需要调整;
  • 2--newDOM和oldDOM末位对比,相同,对比位置同时向前移动,节点位置不需要调整;
  • 3--newDOM末位和oldDOM首位对比,相同,newDOM向前移动,oldDOM向后移动将当前节点移动到oldDOM未比对节点的最后一个节点的后面;
  • 4--newDOM首位和oldDOM末位对比,相同,newDOM向后移动,oldDOM向前移动,将当前节点移动到oldDOM未,比对节点的第一个节点的前面;
  • 若以上四个步骤比对完,并没有相同的节点,则需要将newDOM中的第一个节点,去oldDOM中遍历查询,查找到后,进行移动,并将newStart指针往后移一位;
  • 依次重复上面的过程,直到遍历结束;newDOM中的newStart > newEnd时,说明已经遍历完成了,此时oldDOM中剩余的节点即为待删除节点,在父节点中依次删除就可以了

  1. vue3 diff
  • 在Vue2的四种对比基础上,Vue3只保留了首首对比和尾尾对比,将首首对比和尾尾对比的结果排除后,获取剩下的newDOM节点的最大递增子序列,然后将不在递增子序列中的节点根据子序列的位置进行插入。
  • 存在最大序列中的节点保持不变,不存在的根据最大序列的值来判断插入位置,最终完成newDOM的节点更新;依次往前遍历;






参考&感谢各路大神

Vue3

[vue.js设计与实现-霍春阳]

posted @ 2024-07-25 23:21  安静的嘶吼  阅读(0)  评论(0编辑  收藏  举报