【Vue原理】Diff - 白话版

7,576 阅读5分钟

写文章不容易,点个赞呗兄弟

专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧 研究基于 Vue版本 【2.5.17】

如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧

【Vue原理】Diff - 白话版

终于到了最后一块内容了!今天我们就来简单概括一下 Diff,内容一点都不多哦,全是图片

Diff 作为 Vue 比较重要的一部分内容,还是非常有必要深入了解的

此篇文章就会分几块内容进行简单阐述,不会出现任何的源码,只是为了帮助大家建立一种思路,了解下 Diff 的大概内容

1、Diff 的作用

2、Diff 的做法

3、Diff 的比较逻辑

4、简单的例子

下面就开始我们的正文


Diff 作用

Diff 的出现,就会为了减少更新量,找到最小差异部分DOM,只更新差异部分DOM就好了

这样消耗就会小一些

数据变化一下,没必要把其他没有涉及的没有变化的DOM 也替换了


Diff 做法

Vue 只会对新旧节点中 父节点是相同节点 的 那一层子节点 进行比较

也可以说成是

只有两个新旧节点是相同节点的时候,才会去比较他们各自的子节点

最大的根节点一开始可以直接比较

这也叫做 同层级比较,并不需要递归,虽然好像降低了一些复用性,也是为了避免过度优化,是一种很高效的 Diff 算法

新旧节点是什么

所有的 新旧节点 指的都是 Vnode 节点,Vue 只会比较 Vnode 节点,而不是比较 DOM

因为 Vnode 是 JS 对象,不受平台限制,所以以它作为比较基础,代码逻辑后期不需要改动

拿到比较结果后,根据不同平台调用相应的方法进行处理就好了

想了解 Vnode 更多信息可以转到这篇文章 VNode - 源码版

父节点是相同节点是什么意思?

比如下图出现的 四次比较(从 first 到 fouth),他们的共同特点都是有 相同的父节点

比如 蓝色方的比较,新旧子节点的父节点是相同节点 1

比如 红色方的比较,新旧子节点的父节点都是 2

所以他们才有比较的机会

公众号

而下图中,只有两次比较,就是因为在 蓝色方 比较中,并没有相同节点,所以不会再进行下级子节点比较

公众号


Diff 比较逻辑

Diff 比较的内核是 节点复用,所以 Diff 比较就是为了在 新旧节点中 找到 相同的节点

这个的比较逻辑是建立在上一步说过的同层比较基础之上的

所以说,节点复用,找到相同节点并不是无限制递归查找

比如下图中,的确 旧节点树 和 新节点树 中有相同节点 6,但是然并卵,旧节点6并不会被复用

公众号

就算在同一层级,然而父节点不一样,依旧然并卵

公众号

只有这种情况的节点会被复用,相同父节点 8

公众号

下面说说 Diff 的比较逻辑

1、能不移动,尽量不移动

2、没得办法,只好移动

3、实在不行,新建或删除

比较处理流程是下面这样

在新旧节点中

1、先找到 不需要移动的相同节点,消耗最小

2、再找相同但是需要移动的节点,消耗第二小

3、最后找不到,才会去新建删除节点,保底处理

比较是为了修改DOM 树

其实这里存在 三种树,一个是 页面DOM 树,一个是 旧VNode 树,一个是 新 Vnode 树

页面DOM 树 和 旧VNode 树 节点一一对应的

而 新Vnode 树则是表示更新后 页面DOM 树 该有的样子

这里把 旧Vnode 树 和 新Vnode树 进行比较的过程中

不会对这两棵Vode树进行修改,而是以比较的结果直接对 真实DOM 进行修改

比如说,在 旧 Vnode 树同一层中,找到 和 新Vnode 树 中一样但位置不一样节点

此时需要移动这个节点,但是不是移动 旧 Vnode 树 中的节点

而是 直接移动 DOM

总的来说,新旧 Vnode 树是拿来比较的,页面DOM 树是拿来根据比较结果修改的

如果你有点懵,我们就来就简单说个例子


Diff 简单例子

比如下图存在这两棵 需要比较的新旧节点树 和 一棵 需要修改的页面 DOM树

公众号

第一轮比较开始

因为父节点都是 1,所以开始比较他们的子节点

按照我们上面的比较逻辑,所以先找 相同 && 不需移动 的点

毫无疑问,找到 2

公众号

拿到比较结果,这里不用修改DOM,所以 DOM 保留在原地

公众号

第二轮比较开始

然后,没有 相同 && 不需移动 的节点 了

只能第二个方案,开始找相同的点

找到 节点5,相同但是位置不同,所以需要移动

公众号

拿到比较结果,页面 DOM 树需要移动DOM 了,不修改,原样移动

公众号

第三轮比较开始

继续,哦吼,相同节点也没得了,没得办法了,只能创建了

所以要根据 新Vnode 中没找到的节点去创建并且插入

然后旧Vnode 中有些节点不存在 新VNode 中,所以要删除

公众号

于是开始创建节点 6 和 9,并且删除节点 4 和 5

公众号

然后页面就完成更新啦

怎么样,有没有感兴趣,感兴趣就看源码吧哈哈

后面的就会出源码版啦

最后

鉴于本人能力有限,难免会有疏漏错误的地方,请大家多多包涵,如果有任何描述不当的地方,欢迎后台联系本人,有重谢

公众号