1.理解虚拟DOM和diff算法
1.1什么是虚拟DOM?
从本质上来说,虚拟DOM是一个JavaScript对象,通过对象的方式来表示DOM结构。将页面状态抽象为JS对象的形式,配合不同的渲染工具,使跨平台渲染成为可能。虚拟DOM是DOM的抽象,这个对象是更加轻量级的对DOM的描述。
1.2 为什么要用虚拟DOM?
1. 保证性能下限,在不进行手动优化的情况下,提供过得去的性能。
对比一下修改DOM时真实DOM操作和虚拟DOM的过程,来看一下它们重排重绘的性能消耗:
- 真实DOM:生成HTML字符串+重建所有的DOM元素
- 虚拟DOM:生成vNode+DOMdiff+必要的dom更新
虚拟DOM的更新DOM的准备工作耗费更多的时间,也就是JS层面,相比于更多的DOM操作它的消费是极其便宜的。尤雨溪在社区论坛中说道:框架给你的保证是,你不需要手动优化的情况下,依然可以给你提供过得去的性能。
2. 跨平台
虚拟DOM本质上是JavaScript的对象,它可以很方便的跨平台操作。比如服务器渲染、uniapp等
1.3diff算法简介
新虚拟DOM和旧虚拟DOM进行diff(精细化比较),算出应该如何最小量更新,最后反映到真正的DOM上【虚拟节点变成DOM节点】在Vue里面叫做patch
1.4diff算法原理
在新老虚拟DOM进行对比:
- 首先,对比节点本身,判断是否为同一节点,如果不为相同节点,则删除该节点重新创建节点进行替换
- 如果为相同节点,进行patchVnode,判断如何对该节点的子节点进行处理,先判断一方有子节点一方没有子节点的情况(如果新的children没有子节点,将旧的子节点移除)
- 比较如果都有子节点,则进行updateChildren,判断如何对这些新老节点的子节点进行操作(diff核心)
- 匹配时,找到相同的子节点,递归比较子节点
在diff中,只对同层的子节点进行比较,放弃跨级的节点比较,使得时间复杂度降低至O(n),也就是说只有当新旧children都为多个子节点时才需要用diff算法进行精细化比较。
1.5diff算法什么时候执行?
在页面首次渲染的时候会调用一次patch并创建新的vnode,不会进行更深层次的比较
然后在组件中数据发生变化时,会触发setter然后通过notify通知Watcher,对应的Watcher会通知更新并执行更新函数,它会执行render函数获取新的虚拟DOM,然后执行patch对比上次渲染结果的老的虚拟DOM,并计算出最小的变化,然后再去根据这个最小的变化去更新DOM
1.6diff算法的优化
1.只比较同一层级,不跨级比较
diff过程只会把同颜色并且同一层级的DOM进行比较,这样能够简化比较次数
2.比较标签名
如果同一层级的标签名不同,就直接移除老的虚拟DOM对应的节点,不继续按这个树状结构左深度比较。
3.比较key
如果标签名相同,key也相同,就会认为是相同节点,也不继续按这个树状结构做深度比较。
key的作用
比如有一个列表,我们需要在中间插入一个元素,会导致后面的元素进行重新渲染。如图li1,li2不会重新渲染,li3,li4,li5都会重新渲染。
因为在不使用key或列表的index作为key的时候,每个元素对应的位置关系都是index,上图中的结果导致我们插入的元素到后面的全部元素,对应的位置关系都发生了变更,所以全部都会执行更新操作,而我们希望的是只渲染添加的元素,其他的元素不再进行重新渲染。
而再使用唯一key的情况下,每个元素对应的位置关系都是key,看一下使用唯一key值的情况下,这样图中的li3和li4就不会重新渲染,因为元素内容没有发生改变,对应的位置关系也没有发生改变。
因此,不建议使用index作为key。
原因是:使用index作为key和没写基本上没区别。因为不管数组的顺序怎么颠倒,index都是0,1,2…这样排列,导致Vue会复用错误的旧子节点,做很多额外的工作。
总结:
- 在diff算法中,key是vnode的唯一标记,key的作用主要是为了更高效的更新虚拟DOM,因为它可以非常精确的找到相同节点,因此patch过程会非常高效
- Vue在patch过程中会判断两个节点是不是相同的节点时,key是一个必要条件。在渲染列表时,如果不写key,Vue在比较的时候,就可能会导致频繁更新元素,使整个patch过程比较低效,影响性能。
- 应该避免使用数组下标作为key,因为key值不是唯一的话,也可能会出现上面图中的问题,还有比如在使用相同标签元素过渡切换的时候,就会导致只替换其内部属性,而不会触发过渡效果。这个时候key的作用是用来表示一个独立的

本文详细探讨了虚拟DOM的概念及其优势,包括为何使用虚拟DOM以确保性能和跨平台操作。接着,解释了diff算法的原理,何时执行以及如何优化,如仅比较同一层级、比较标签名和key的作用。还介绍了Vue中实现虚拟DOM和diff的具体步骤,如h函数、vnode、patch、createElement等。最后,强调了key在优化diff过程中的关键作用,以及不恰当使用key可能导致的问题。
最低0.47元/天 解锁文章
509

被折叠的 条评论
为什么被折叠?



