Vue的常见问题(四) - 对于diff算法的理解

前言

diff算法是虚拟DOM技术的必然产物:通过新旧虚拟DOM作对比(即diff),将变化的地方更新在真实DOM上;另外,也需要diff高效的执行对比过程,从而降低时间复杂度为O(n)

diff算法并不是Vue独有的,只要涉及到虚拟dom的框架都有在使用,比如react。

我们这里讨论的是diff算法在Vue中的运用,主要从三个方面讨论:必要性,执行方式和高效性。

一、必要性

diff算法的必要性,我们可以结合Vue源码进行讨论,

我们知道 ,一个Vue实例在创建后执行$mount()挂载时,会调用mountComponent()。其中,会创建一个Watcher,也就是说一个组件对应一个reader Watcher。

关于“Vue的初始化过程”的详细解析可以看下《vue2源码解析(一) - new Vue()的初始化过程》

但是,组件中可能存在多个data中key的使用,那么Watcher如何确保每个key发生变化时如何进行视图更新呢?

所以,这个问题就能说明diff算法的必要性了。

因为,当需要进行页面视图更新时,可以利用diff算法对新旧两个vnode进行比较,从而能准确地知道哪里发生了变化,最后进行页面视图更新。

总结:vue2.x中为了降低Watcher粒度,每个组件只有一个Watcher与之对应,只有引入diff才能精确找到发生变化的地方。

二、执行方式和高效性

vue中diff执行的时刻是组件实例执行其更新函数时,它会比对上一次渲染结果oldVnode和新的渲染结果newVnode,此过程称为patch。

整体流程:

  1. 响应式数据的修改;
  2. 触发dep.notify();
  3. 触发Watcher的update();
  4. 会将Watcher对应的更新方法增加到异步更新(微任务)队列中;
  5. 当一个宏任务结束,会清空微任务队列中的任务,也就是会执行Watcher的更新方法;
  6. 从而执行组件的更新渲染函数,就会触发patch()。

详细解析可以看下《vue2源码解析(三) - Vue的批量异步更新策略与$nextTick》

diff算法的整体策略是:深度优先,同层比较。

  1. 两个节点之间比较会根据它们是否拥有子节点或者文本节点做不同操作;
  2. 比较两组子节点是算法的重点,首先假设头尾节点可能相同做4次比对尝试,如果没有找到相同节点才按照通用方式遍历查找,查找结束再按情况处理剩下的节点;

借助key通常可以非常精确找到相同节点,因此整个patch过程非常高效。

可参考《Vue的常见问题(三) - key的作用和工作原理》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值