Vue 源码-diff算法
2021-02-23 本文已影响0人
Viewwei
- 虚拟 DOM 概念
虚拟 DOM是对 DOM 的 js 抽象表示,能够描述 DOM 结构和关系,应用的各种状态变化作用于虚拟 DOM,最终映射到 DOM 上. - 虚拟 DOM 的优点
虚拟 DOM 轻量,快速:当它们发生变化的时候,会通过新旧虚拟 DOM 对比可以得到最小 DOM 操作量,配合异步更新策略减少刷新频率,提升性能.虚拟 DOM 更新转换为不同运行时的特殊操作实现跨平台而且拥有很好的兼容性
Vue 中如何使用虚拟 DOM 实现界面更新的?
-
Vue 的组件的更新入口是updateComponent函数,下图是updateComponent函数的实现情况.组件的初始化和组件的更新都是从这个入口进入的.vm.render函数其实就是当真实节点转换成虚拟DOM 的操作.
src/core/instance/lifecycle.js -
vm._update函数内部是实现如下图所示.在初始化的时候 prevnode 为空执行,执行初始化操作
src/core/instance/lifecycle.js -
下图是 patch函数内部实现情况,在进入之前首先判断是否定义了老的虚拟节点.在初始化的时候,没有老的虚拟节点.然后判断当前节点是不是真实节点.在初始化的过程中,是真实节点.
src/core/vdom/patch.js
下图的标注 1 表示创建一个老的虚拟节点,标注 2 表示拿出真实节点并且拿到真实节点的父节点(body)
src/core/vdom/patch.js
下图表示创建一个新的真实节点,并且插入的以前的真实节点的后面,然后把以前的真实节点删除.界面的初始化完成.
src/core/vdom/patch.js
当界面发生改变的时候,会再次进入 updateComponent 函数,由于 prevnode函数不为空,进入更新流程
src/core/instance/lifecycle.js
进入 path 函数的更新流程,进入patchVnode函数
src/core/vdom/patch.js
下图是patchVnode函数的实现方法,更新进入 updateChildren
src/core/vdom/patch.js - patch 的实现
path 函数其实就是级别的比较,一般三种情况:增删改.patchVnode 函数其实就是比较两个虚拟 DOM,其中的操作包括属性更新,文本更新,子节点更新.比较的原则坚持同级比较,深度优先的原则. - 比较规则如下
- 新老节点均有children子节点,则对子节点进行diff操作,调用updateChildren
- 如果新节点有子节点而老节点没有子节点,先清空老节点的文本内容,然后为其新增子节点。
- 当新节点没有子节点而老节点有子节点的时候,则移除该节点的所有子节点。
-
当新老节点都无子节点的时候,只是文本的替换。
下图展示的是updateChildren函数内部实现情况
1.标注老的开始节点没有定义
2,标识标识老的结束节点没有定义
3.标注表示新的开始节点和老的开始节点一样
4标注标识老的结束节点和新的结束节点一致
5 标注标识老的开始节点好新的结束节点一致
6标注表示老的结束节点和新的开始节点一致
7 表示正常遍历
image.png