|快看,VUE对你的页面做了什么


|快看,VUE对你的页面做了什么
本文插图

转载本文需注明出处:微信公众号EAWorld , 违者必究 。
讲过了Vue的响应式原理 , 那就不得不说说和它息息相关的diff算法的实现 。 响应式系统会监听发生改变的数据并将相关组件重新渲染 。 其实 , 即便没有响应式 , 也可以通过操作DOM节点来更新数据显示 , 但是这样做的代价实在太大 , 降低页面性能 , 因此产生了Virtual DOM , 它的主要思想是利用JavaScript对象按照真实的DOM结构来抽象出一个虚拟DOM结构 , 并在需要更新某些节点时 , 进行新旧对比 , 找出需要更新的节点后 , 仅仅对需要重新渲染的节点进行更新 , 这样就大大提高页面性能 。 不仅仅是Vue , React也使用了Virtual DOM技术来优化渲染效率 。
Virtual DOM中负责将新旧DOM树中的节点进行对比并找出发生变更的节点这一工作是由diff来进行的 , diff是Virtual DOM较为核心的部分 , 要对比两棵层级复杂的DOM树 , diff的时间复杂度直接影响了新旧节点替换的性能 。 Vue实践的diff算法仅仅对同级的节点进行比较 , 因此时间复杂度为O(n) 。 如下图 , diff算法仅对颜色相同的方框中的节点进行对比 。

|快看,VUE对你的页面做了什么
本文插图

Diff算法首先对比新旧节点 , 这一对比仅在同层节点间进行 。 由于对比过程源码比较复杂且篇幅巨大 , 有兴趣的同学可以去github上看看 , 这里仅对算法进行解析 , 因此就不搬运源码了 。
需要说明一下 , 在接下来的对比算法中 , 相同节点的概念 , 指的是两个节点的key、tag等在第一次渲染时打上的各种标识唯一DOM界的的标记、属性均一致 , 而不是包含它所带的值 , 样式颜色等 。 Patch操作说的是将两个节点进行对比将发生变化的一些属性更新 , 如果两个节点均包含子节点 , 那么对他们的子节点同样进行diff对比 。 在找出同层的两组新旧节点后 , 分别为他们打上开始和结束的标志 , 在对比过程中 , 开始和结束的标志不断向中间靠拢 , 直到新节点队列或旧节点队列中有一个的开始标志到结束标志之后 , 那么对比就完成了 , 整个对比过程如下图:

|快看,VUE对你的页面做了什么
本文插图

算法首先将四个被打了标记的节点做如下六种情况对比:
一、NewStart和OldStart
如果是同一节点那么直接将这两个节点进行patch操作 , NewStart和OldStart标志后移到下一个节点
二、NewStart和OldEnd
如果是同一节点 , 将OldEnd节点移到OldStart前 , 标志前移一个节点 , NewStart后移一个节点

|快看,VUE对你的页面做了什么
本文插图

三、NewEnd和OldStart
如果是同一节点 , 将OldStart节点移到OldEnd后 , OldStart后移一个节点 , NewEnd前移一个节点

|快看,VUE对你的页面做了什么
本文插图


|快看,VUE对你的页面做了什么
本文插图

四、NewEnd和OldEnd
如果是同一节点那么直接将这两个节点进行patch操作
五、与NewStart相同的节点在旧节点队列中
如果以上情况皆不满足 , 那么就在旧的节点队列中进行一次遍历对比 , 找出与NewStart相同的节点 , 后将该节点前移到OldStart前

|快看,VUE对你的页面做了什么
本文插图


推荐阅读