写文章不容易,点个赞呗兄弟
专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧
研究基于 Vue版本 【2.5.17】
如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧
终于到了最后一块内容了!今天我们就来简单概括一下 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
然后页面就完成更新啦
怎么样,有没有感兴趣,感兴趣就看源码吧哈哈
后面的就会出源码版啦
最后
鉴于本人能力有限,难免会有疏漏错误的地方,请大家多多包涵,如果有任何描述不当的地方,欢迎后台联系本人,有重谢
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。