写文章不容易,点个赞呗兄弟
专注 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
然后页面就完成更新啦
怎么样,有没有感兴趣,感兴趣就看源码吧哈哈
后面的就会出源码版啦
最后
鉴于本人能力有限,难免会有疏漏错误的地方,请大家多多包涵,如果有任何描述不当的地方,欢迎后台联系本人,有重谢