首页 > 编程语言 >虚拟DOM与Diff算法

虚拟DOM与Diff算法

时间:2022-08-17 18:24:08浏览次数:86  
标签:oldVnode DOM 更新 vnode 算法 虚拟 Diff 节点

参考

真实DOM的渲染

在讲虚拟DOM之前,先说一下真实DOM的渲染。

 

浏览器真实DOM渲染的过程大概分为以下几个部分:

  1. 构建DOM树。通过html parser解析处理html标记,将它们构建为DOM树(DOM tree),当解析器遇到非阻塞资源(图片,css),会继续解析,但是如果遇到script标签(特别是没有async 和 defer属性),会阻塞渲染并停止html的解析,这就是为啥最好把script标签放在body下面的原因。

  2. 构建cssOM树。与构建DOM类似,浏览器也会将样式规则,构建成CSSOM。浏览器会遍历CSS中的规则集,根据css选择器创建具有父子,兄弟等关系的节点树。

  3. 构建Render树。这一步将DOM和CSSOM关联,确定每个 DOM 元素应该应用什么 CSS 规则。将所有相关样式匹配到DOM树中的每个可见节点,并根据CSS级联确定每个节点的计算样式,不可见节点(head,属性包括 display:none的节点)不会生成到Render树中。

  4. 布局/回流(Layout/Reflow)。浏览器第一次确定节点的位置以及大小叫布局,如果后续节点位置以及大小发生变化,这一步触发布局调整,也就是 回流。

  5. 绘制/重绘(Paint/Repaint)。将元素的每个可视部分绘制到屏幕上,包括文本、颜色、边框、阴影和替换的元素(如按钮和图像)。如果文本、颜色、边框、阴影等这些元素发生变化时,会触发重绘(Repaint)。为了确保重绘的速度比初始绘制的速度更快,屏幕上的绘图通常被分解成数层。将内容提升到GPU层(可以通过tranform,filter,will-change,opacity触发)可以提高绘制以及重绘的性能。

  6. 合成(Compositing)。这一步将绘制过程中的分层合并,确保它们以正确的顺序绘制到屏幕上显示正确的内容。

虚拟DOM

虚拟DOM本质上是一个js对象,通过对象来表示真实的DOM结构。tag用来描述标签,props用来描述属性,children用来表示嵌套的层级关系。

 

const vnode = {
    tag: 'div',
    props: {
        id: 'container',
    },
    children: [{
        tag: 'div',
        props: {
            class: 'content',
        },
          text: 'This is a container'
    }]
}
 
 
//对应的真实DOM结构
<div id="container">
  <div class="content">
    This is a container
  </div>
</div>

虚拟DOM的更新不会立即操作DOM,而是会通过diff算法,找出需要更新的节点,按需更新,并将更新的内容保存为一个js对象,更新完成后再挂载到真实dom上,实现真实的dom更新。

虚拟DOM优点(上面引出的)(这就是为啥需要虚拟DOM

总结起来,虚拟DOM的优势有以下几点:

  1. 小修改无需频繁更新DOM,框架的diff算法会自动比较,分析出需要更新的节点,按需更新

  2. 更新数据不会造成频繁的回流与重绘

  3. 表达力更强,数据更新更加方便

  4. 保存的是js对象,具备跨平台能力

不足

虚拟DOM同样也有缺点,首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。

虚拟DOM实现原理

主要分三部分:

  1. 通过js建立节点描述对象

  2. diff算法比较分析新旧两个虚拟DOM差异

  3. 将差异patch到真实dom上实现更新

Diff算法

为了避免不必要的渲染,按需更新,虚拟DOM会采用Diff算法进行虚拟DOM节点比较,比较节点差异,从而确定需要更新的节点,再进行渲染。vue采用的是深度优先,同层比较的策略。

2e41e4f6bd68ca346c52492440e29540.png

新节点与旧节点的比较主要是围绕三件事来达到渲染目的

  1. 创建新节点

  2. 删除废节点

  3. 更新已有节点

 patch 函数代码:

//patch函数 oldVnode:老节点 vnode:新节点
function patch (oldVnode, vnode) {undefined
 ...
 if (sameVnode(oldVnode, vnode)) {undefined
 patchVnode(oldVnode, vnode) //如果新老节点是同一节点,那么进一步通过patchVnode来比较子节点
 } else {undefined
 /* -----否则新节点直接替换老节点----- */
 const oEl = oldVnode.el // 当前oldVnode对应的真实元素节点
 let parentEle = api.parentNode(oEl) // 父元素
 createEle(vnode) // 根据Vnode生成新元素
 if (parentEle !== null) {undefined
  api.insertBefore(parentEle, vnode.el, api.nextSibling(oEl)) // 将新元素添加进父元素
  api.removeChild(parentEle, oldVnode.el) // 移除以前的旧元素节点
  oldVnode = null
 }
 }
 ...
 return vnode
}
 
//判断两节点是否为同一节点
function sameVnode (a, b) {undefined
 return (
 a.key === b.key && // key值
 a.tag === b.tag && // 标签名
 a.isComment === b.isComment && // 是否为注释节点
 // 是否都定义了data,data包含一些具体信息,例如onclick , style
 isDef(a.data) === isDef(b.data) && 
 sameInputType(a, b) // 当标签是<input>的时候,type必须相同
 )
}

 

标签:oldVnode,DOM,更新,vnode,算法,虚拟,Diff,节点
From: https://www.cnblogs.com/the-big-dipper/p/16596278.html

相关文章

  • js算法基础-栈结构的封装和进制转换
    先是栈结构的封装,使用es6的方式。#items为栈结构#表示类的私有属性,外部不能直接访问和修改。push压栈pop出栈peek查看栈顶isEmpty栈是否为空size栈内元素个数......
  • 递归算法的使用
    1packageIO;2importjava.io.File;34/**5*需求:给定一个路径,通过递归算法遍历该目录下所有内容;6*并将所有文件的绝对路径输出来;7*/8publicc......
  • 目标跟踪【1】-质心跟踪算法
    基本思路:1.通过某种方式获取目标的边界框,计算边界框的质心2.在后续帧中,同样获取边界框、质心3.重点来了,先验知识认为当前物体的质心和下一帧同一目标的质心的距离......
  • Randomizing Object Handle
    您可以将对象句柄声明为“rand”。在这种情况下,该对象的所有变量和约束都是随机的。随机化不会修改实际的对象句柄。此外,对象句柄不能声明为“randc”。下面是一个例子:cl......
  • Randomizing Arrays and Queues
    您可以随机化动态数组、关联数组和队列。可以将它们声明为“rand”或“randc”,这将导致数组的所有元素被随机化。数组中的所有元素都是随机的,每次随机(调用randomize())会......
  • 算法工程师是做什么的?
    随着大数据和人工智能领域的不断深入发展,自然语言处理、机器学习等方向成为求职的大热门,算法工程师也自然而然成为目前最炙手可热的岗位。虽然算法工程师一直被频频提及,但......
  • 2022“杭电杯”中国大学生算法设计超级联赛(9)
    赛后总结:不太理解为什么都这么强,1008是一道欧拉函数变形,我用莫比乌斯反演推出了一样的式子,实际上两个1e7的数的质数集合的并最多只有12个,那么暴力按照式子2^12枚举每个质......
  • 2022“杭电杯”中国大学生算法设计超级联赛(7)
    比赛链接:https://vjudge.net/contest/509567B-IndependentFeedbackVertexSet题意:定义无向无环图为森林,集合中任意两点之间没有边相连的集合为独立集。现在有\(n......
  • 排序算法
    1. 排序算法面试中 面试高频又快排、堆排和归并排序先说快排,快排体现的的思想是:分而治之,并且递归 怎么个分呢,选第一个数进行强行将数据分成两拨。此时需要一个函......
  • LeetCode 螺旋矩阵 II 算法题解 All In One
    LeetCode螺旋矩阵II算法题解AllInOnejs/ts生成螺旋矩阵螺旋矩阵原理图解动态赋值arr[i]//动态更新indexleti=0;while(left<=right&&t......