Vue3进阶主题: 渲染性能提升之diff算法优化 您所在的位置:网站首页 vue怎么操作虚拟dom Vue3进阶主题: 渲染性能提升之diff算法优化

Vue3进阶主题: 渲染性能提升之diff算法优化

#Vue3进阶主题: 渲染性能提升之diff算法优化| 来源: 网络整理| 查看: 265

问题引入 为什么要使用diff算法? 什么是diff算法? 问题解释

为了减少DOM操作, 减少浏览器开销。

DOM元素数量多:页面中的DOM元素非常多,每个DOM元素的状态和属性都需要被计算和更新,这就会带来很大的性能开销。 DOM操作引起浏览器重绘和重排:当我们修改DOM元素时,会引起浏览器对页面进行重绘和重排。这个过程会耗费大量的计算资源,如果频繁地修改DOM元素,会导致页面的性能变得很差。 JavaScript与DOM之间的交互开销大:当JavaScript代码需要操作DOM元素时,需要通过浏览器的API来完成,而这个过程涉及到JavaScript代码和浏览器引擎之间的交互,会产生一定的开销。 DOM操作会触发页面回流:在执行一些DOM操作时,浏览器会重新计算元素的大小和位置,这个过程叫做回流(reflow)。回流会导致页面中的其他元素重新布局,从而增加页面的开销。

因此,为了提高页面性能,通过使用diff算法减少DOM操作。

diff算法是一种基于虚拟DOM的算法,用于比较前后两个状态下的虚拟DOM树,并计算出最小的操作来更新DOM树,以实现高效的渲染性能。

Vue2 diff算法

Vue2的diff算法采用的是基于虚拟DOM树的双端比较算法,也称为VNode的patch算法。它将新旧两棵虚拟DOM树的VNode节点进行深度优先遍历,一边遍历一边进行比较,并更新需要更新的节点,最终生成新的VNode树,然后将新的VNode树渲染成实际的DOM。

源码解析 return function patch(oldVnode, vnode) { let isInitialPatch = false const insertedVnodeQueue = [] // 如果新的 vnode 不存在,则销毁旧的 vnode if (isUndef(vnode)) { if (isDef(oldVnode)) invokeDestroyHook(oldVnode) return } // 如果旧的 vnode 不存在,则创建新的 vnode 的 DOM 元素 if (isUndef(oldVnode)) { isInitialPatch = true createElm(vnode, insertedVnodeQueue) } else { // 判断 oldVnode 是否为真实元素 const isRealElement = isDef(oldVnode.nodeType) if (!isRealElement && sameVnode(oldVnode, vnode)) { // 更新现有的根节点 patchVnode(oldVnode, vnode, insertedVnodeQueue) } else { // 如果 oldVnode 是真实元素 if (isRealElement) { // 如果是服务端渲染的内容并且可以成功合并,则进行合并 if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) { oldVnode.removeAttribute(SSR_ATTR) } if (isTrue(hydrating)) { if (hydrate(oldVnode, vnode, insertedVnodeQueue)) { invokeInsertHook(vnode, insertedVnodeQueue, true) return oldVnode } else if (__DEV__) { warn('...') } } oldVnode = emptyNodeAt(oldVnode) } // 替换现有元素 const oldElm = oldVnode.elm const parentElm = nodeOps.parentNode(oldElm) createElm(vnode, insertedVnodeQueue, oldElm._leaveCb ? null : parentElm, nodeOps.nextSibling(oldElm)) // 递归更新所有的祖先占位符节点 if (isDef(vnode.parent)) { let ancestor = vnode.parent const patchable = isPatchable(vnode) while (ancestor) { ancestor.elm = vnode.elm if (patchable) { for (let i = 0; i < cbs.create.length; ++i) { cbs.create[i](emptyNode, ancestor) } } else { registerRef(ancestor) } ancestor = ancestor.parent } } // 删除旧的节点 if (isDef(parentElm)) { removeVnodes([oldVnode], 0, 0) } else if (isDef(oldVnode.tag)) { invokeDestroyHook(oldVnode) } } } invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch) return vnode.elm } 复制代码 Vue3 diff算法

Vue3的diff算法基于最长递增子序列(LIS)算法进行优化,以减少 VNode 的比较次数,提高diff算法的效率。

最长递增子序列(LIS)

最长递增子序列是一个非常经典的算法问题,它的问题描述为:给定一个数列,求其中最长的一个子序列,使得子序列中的数是递增的。

function longestIncreasingSubsequence(nums) { if (!nums.length) { // nums为空的情况 return 0; } const tops = []; // 堆顶集合 for (const num of nums) { // 二分查找num应该插入的位置 let left = 0, right = tops.length - 1; while (left


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有