【源码】vue2 patch源码刨析

【公司内部分享】探索Vue.js框架内部原理和实现机制,旨在理解其核心概念和技术细节,以便更好地应用和定制Vue.js。

相关文章

环境

  • vue:v2.6.1

vue2 patch源码刨析


一、什么是虚拟DOM

什么是虚拟DOM

本质就是一个通过状态树来描述DOM节点树的普通js对象

如何创建虚拟DOM

二、为什么要引入虚拟DOM

  • 1:虚拟DOM是时代发展的产物,从过去JQuery时代的命令式操作DOM转为声明式操作DOM已经势在必行。
  • 2:由于虚拟DOM是抽象描述节点间的状态关系,不依赖真实的平台环境,因此还具备跨平台的优势。

基本原理

  • 1:使用栈维护AST层级,遇到开始标签则把当前节点推入栈,遇到结束标签则把当前节点弹出栈
  • 2:四个钩子函数(start,end,chars,comment)

工作流程

每截取一小段字符串,就会根据截取出来的字符串类型触发不同的钩子函数,直到模板字符串截空停止运行

三、Patch 的工作流程

基本规则

  • 1:新节点不存在,执行删除
  • 2:旧节点存在、新节点存在、执行diff(重点)
  • 3:旧节点存在,新节点不存在、执行删除

如何确认为同一节点

Key相同、当前节点的标签名相同、isComment相同(注释节点属性)、data都有或都没有定义、当标签是input的时候type相同

四、PatchVnode 的工作流程

基本规则

  • 1:相同节点或都是静态节点直接退出
  • 2:新旧都有文本节点且不一样则修改文本,否则执行新增或删除
  • 3:新旧都有子节点且不一样则直接updateChildren(DIFF),否则执行新增或删除

五、Diff基本规则与目的

基本规则

  • 1、只在同层级之间进行比较,不会跨层级比较,时间复杂度只有O(n)
  • 2、优先深度遍历所有节点进行比较,直到完成再去比较当前节点的下一个同层级节点

目的

  • 为了减少更新量,找到最小差异部分DOM,进行patch

六、DIFF的工作流程

差异

  • 1)新增节点11
  • 2)删除节点8
  • 3)1,10节点未变化
  • 4)2、3、4、5、6、7节点位置变化

Step1 处理头头\尾尾同类节点

即oldStart和newStart ,以及oldEnd和newEnd指向同类节点的情况,如图中的节点1和节点10,移动之后标记该节点,若节点有更新则同步进行更新,同时将newStart、oldStart各后移1位,newEnd、oldEnd各前移一位

Step2 处理头尾\尾头同类节点

即oldStart和newEnd,以及oldEnd和newStart指向同类节点的情况,如图中的节点2和节点9,移动之后标记该节点,若节点有更新则同步进行更新,同时将newStart、oldStart各后移1位,newEnd、oldEnd各前移一位

Step3 处理新增的节点

此时newStart来到了节点11的位置,在oldVdom中找不到节点11,说明它是新增的,那么就创建一个新的节点,插入DOM树,插到oldStart指向的节点(即节点3)前面

Step4 处理更新的节点

此时newStart来到了节点7的位置,在oldVdom中能找到它但不在指针位置,说明它是移动的,那么将节点7移到oldStart指向的节点(即节点3)前面,与此同时将节点标记为已处理

Step5 重复步骤1

此时我们看到了令人欣慰的一幕,newStart和oldStart又指向了同一个节点(即都指向节点3),此时再按照(Step1)中的做法只需移动指针即可,3、4、5、6都同样处理

Step6 处理删除的节点

此时newStart跨过了newEnd,它们相遇了!而oldStart和oldEnd还没有相遇,说明这2个指针之间的节点(包括它们指向的节点,即图中的节点7、节点8)是此次更新中被删掉的节点

Tip

还记得前面我们对节点7做了标记吗,标记的目的是告诉Vue它已经处理过了,是需要出现在新DOM中的节点,不要删除它,所以在这里正在删除的只有节点8

DIFF完成

整个过程是逐步找到更新前后vdom的差异,然后将差异反应到DOM树上(也就是patch),提醒:Vue的patch是即时的,并不是打包所有修改最后一起操作DOM(React则是将更新放入队列后集中处理)[ PS:现代浏览器对这样的DOM操作做了优化,不要担心 ]


喜欢这篇文章?打赏一下支持一下作者吧!
【源码】vue2 patch源码刨析
https://www.cccccl.com/20201102/源码/vue/vue2 patch源码刨析/
作者
Jeffrey
发布于
2020年11月2日
许可协议