从源码角度解析Vue重排与重绘

众所周知,Vue通过数据绑定来修改视图,当某个数据被修改的时候,set方法会让闭包中的Dep调用notify通知所有订阅者WatcherWatcher通过get方法执行vm._update(...),进而去更新视图。

vm._update(...)中,Vue会调用patch(...)(vdom/patch.js第659行左右),将新产生的vnode与数据未变更之前的旧的prevVnode进行对比。

patch(...)方法中,Vue通过sameVnode(...)(vdom/patch.js第42行左右)对新旧两个Vnode对象进行比较,通过比对它们的标签名(tag)、键值(key)、是否都拥有data选项(isDef(data))以及是否都为注释节点(isComment)来确定这两个Vnode映射的真实DOM节点为同一个。只有确定它们是同一个真实DOM节点的不同映射时,才会执行下一步patchVnode(...)(vdom/patch.js第501行左右)。

patchVnode(...)中,Vue会依据新旧两个Vnode对象是否拥有子节点children执行不同的DOM操作,当两个Vnode对象都有子节点时,会调用updateChildren(...)(vdom/patch.js第501行左右)方法递归的对子节点进行patchVnode(...)

Vue中的diff算法

请注意,diff算法是一个使用了递归思想的算法,但是它的时间复杂度只有O(n),这是因为,每一个旧的Vnode只跟与它同层的映射为同一个真实DOM节点的新Vnode进行比较

从源码角度解析Vue重排与重绘

这里有一篇很好的专门讲解diff算法的文章链接