Vue2 - diff 原理(动图演示)

1,diff

解释:对比新旧虚拟DOM树,完成对真实DOM的更新,这个对比差异的过程叫做 diff

Vue 会在内部的 patch 函数中完成该过程。

diff 的时间点

当组件创建时,或依赖的数据变化时,会运行一个特定的函数来做2件事:

  • 运行 _render 函数生成新的 VNode tree(虚拟DOM树)
  • 运行 _update 函数,传入新的 VNode tree 的根节点,对比新旧2个树,最终完成对真实DOM的更新。

代码表示大致逻辑:

// vue构造函数
function Vue(){
   
   
  // ... 其他代码
  var updateComponent = () => {
   
   
    this._update(this._render())
  }
  new Watcher(updateComponent);
  // ... 其他代码
}

diff 就发生在_update函数的运行过程中

Watcher 的作用:简单来说,运行传入的函数(updateComponent),对函数中用到的响应式数据进行依赖收集。

Watcher 的作用具体参考Vue2-数据响应式原理

2,_update 函数

  1. _update 函数接收一个 VNode 参数,也就是this._render() 返回的生成的虚拟 DOM 树。

  2. _update 函数通过当前组件的 this._vnode 属性,拿到的虚拟 DOM 树。

  3. _update 函数首先会给组件的 this._vnode 属性重新赋值,让它指向新树。再判断旧树是否存在:

    • 不存在,说明是第一次加载组件,则通过 patch 函数直接遍历新树,为每个节点生成真实的DOM,并挂载到每个节点的 elm 属性上。(虚拟节点通过 elm 属性指向绑定的真实DOM。)
    • 存在,说明之前已经渲染过组件,则通过 patch 函数对新旧树对比,来实现2个目标:
      • 完成对所有真实 DOM 的最小化处理。
      • 让新树的节点对应合适的真实DOM。

不存在的流程:
不存在的流程
存在时的流程:
不存在时的流程

// 伪代码表示:
function update(vnode) {
   
    // 参数是新 vnode
  const oldVnode = this._vnode
  this._vnode = vnode
}

这样就完成了组件的虚拟DOM树的更新

但还需要解决真实的 DOM 更新(如果不考虑效率,直接用新树生成真实DOM即可)。而为了提升效率,需要对比新旧树,通过实现下面2个目标来提升效率。这个步骤在 _patch 函数中实现。

  • 完成对所有真实 DOM 的最小化处理。
  • 让新树的节点对应合适的真实DOM。

3,_patch 函数(进行 diff)

先来介绍几个术语,方便后续阅读:

  1. 【相同】:指2个虚拟节点的标签(tag)类型、key 值均相同。input 元素还需要考虑 type 属性。<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下雪天的夏风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值