iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >详解react应用中的DOM DIFF算法
  • 330
分享到

详解react应用中的DOM DIFF算法

2024-04-02 19:04:59 330人浏览 八月长安
摘要

目录前言 什么是Virtual DOM? 使用Virtual DOM的原因 DOM 渲染页面的操作流程 Virtual DOM的优势如何将DOM用virtual DOM 来表

前言

对我们搞前端的来说,目前最流行的两大前端框架毫无疑问当属ReactVue,对于这两大框架,想必大家也是再熟悉不过了。然而,这两大框架无一例外的全部放弃使用传统的DOM技术,却采用了以js为基础的Virtual DOM技术,也可称作虚拟DOM。所以,到底什么是Virtual DOM?两大热门框架全部使用Virtual DOM的原因又是什么?接下来让我这个搞前端的人来好好地为您讲解一下DOM DIFF算法的牛逼之处。

什么是Virtual DOM?

如字面意思所说,Virtual DOM即 虚拟DOM,它的特点就是利用javascript来模拟DOM结构,并且将DOM的变化对比放在JS层中进行比较。具体操作如下:


// 普通的html DOM结构
<ul class="list">
   <li class="item">wjy</li>
   <li class="item">易烊千玺</li>
</ul>

// 映射出的虚拟DOM
{
   tag:'ul',
   props:{
       class:'list'
   },
   children: [
       {
           tag:'li',
           props:{
               class:'item'
           },
           children: ['易烊千玺']
       }
   ]
}

有朋友或许会有点迷惑,普通的HTML DOM结构不好吗?通俗易懂,代码也更加简洁,为什么还需要采用嵌套递归的虚拟DOM形式呢?其实这和普通DOM在重新渲染的过程中非常消耗性能有关,DOM操作看似简便,但其实效率相当低,这是因为如果是在需要频繁修改的真实DOM中,看起来更加复杂的运用JS结构的Virtual DOM效率会更高.

使用Virtual DOM的原因

DOM 渲染页面的操作流程

  • 当浏览器通过域名从服务器拿到对应的HTML文件后,浏览器首先会进行构建DOM树和CSSOM树,关于树的概念,学过数据结构与算法的同学或许对树的节点概念印象深刻。
  • 在HTML DOM中,所有的事物都是节点,而DOM是被视为节点树的HTML,并且,各个节点之间有着相应的层级关系。DOM节点树和HTML中的标签一一对应,构成了DOM树
  • HTML文件

  • HTML DOM树

同样的。在CSS文档中,所有的元素也皆是节点,与HTML中的标签一一对应,构成了CSSOM树 如下图所示

警告! 如果在构建DOM树的过程中,有遇到JS相关的内容时,DOM树的构建会立即停止,这是由于,JS可以对DOM节点进行操作,浏览器为了防止JS会对以完成的DOM造成影响,会阻止DOM树的构建,以节约资源。

在DOM树和CSSOM树不断构建的过程中,渲染树也在逐渐形成,浏览器会根据所构建的渲染树进行网页布局和绘制流程,不断地进行网页的搭建。具体操作流程图如下:

一般而言,对于页面渲染的常规操作,我们通常是操作DOM,修改并重置innerHTML完成页面的渲染,每进行一次DOM的更新操作,都会重新进行一次渲染流程,这个过程包含着页面的重绘和重排。

Virtual DOM的优势

但是如果对于大型页面项目,或者具有多标签,多属性的网页而言,常规的DOM操作实在是太耗时了,每次的简单修改都需要牵动大量的DOM节点的重绘与重排,极大地降低了页面渲染效率.于是,当前端开发人员面对DOM瓶颈一筹莫展的时候,Virtual DOM显示出了作为轻量级的JavaScript对象的极大优越性,顺利得到了了前端开发者的青睐。

在页面进行重新渲染的时候,Virtual DOM进行dom diff计算对比两次并发现其中的差异,只需要修改DOM树中不同的部分即可.也可以理解为Virtual DOM做了一个中间件,先利用JS修改Virtual DOM,在对比出差异后,将所有的更改加入页面的真实DOM.所以说,Virtual DOM的最大优势就在于完全不用像原生DOM,在对比之后还要进行DOM的重建与创造,因为这对于大型项目的运行来说非常消耗性能,开销极大.由此可见,不论在什么体量的网页中,放弃传统DOM采用Virtual DOM无疑是非常高效且绝佳的选择.

如何将DOM用virtual DOM 来表示

首先,在vscode中新建一个dom diff 项目,项目初始化,装好相应组件

由于是DOM树,所以在将HTML转换成DOM树时,要运用递归的形式,首先创建结点,其次设置属性,然后设置子节点


<ul class="list">
    <li class="item">wjy</li>
    <li class="item">易烊千玺</li>
</ul> 

// DOM 树的表达转换形式 
let virtualDOM = createElement('ul', {
  class:'list',
}, [
  createElement('li',{
    class:'item'
  },['wjy']),
  createElement('li',{
    class:'item'
  },['易烊千玺']),
])

然后,在新建一个element.js文件进行向外输出,完成页面渲染


// 通过构造函数Element构造虚拟DOM节点
class Element {
    constructor(type,props,children){
        this.type = type;
        this.props = props;
        this.children =children;
    }
}
// 
const createElement = (type,props,children) => { 
  return new Element(type,props,children);
}

// 进行页面渲染 将Virtual Dom转化为真实DOM
const render = (domObj) => {  
    let el = document.createElement(domObj.type);
    for(let key in domObj.props){
        setAttr(el,key,domObj.props[key]);
    }
    domObj.children.forEach(child => {
        child = (child instanceof Element)
        ? render(child)
        : document.createTextnode(child);
        el.appendChild(child);

    })
    return el;
}

function setAttr(node,key,value){
    switch(key){
        case 'value':
            if(node.tagName.toLowerCase() === 'input' || 
            node.tagName.toLowerCase() ==='textarea'
            ){
                node.value = value;
            }else{
                node.setAttribute(key,value)
            }
            break;
            case 'style':
            //   node.setAttribute('style',value)
            node.style.cssText = value;
            break;
            default:
                node.setAttribute(key,value)
            break;
    }
}

// 将真实DOM 挂载到制定根节点
const renderDOM = (el,target) => {
    target.appendChild(el);
}

// 向外输出
export {
    createElement,
    render,
    renderDOM
}

在控制台上得到真实DOM

页面渲染成功!😃

DOM DIFF算法

在用户进行操作更改交互页面操作后,虚拟DOM树上的节点会发生变化,然而此时真实节点却没有改变,为了使得更改与真实页面同步,我们会使用DOM DIFF算法找出这两颗树的差异,然后产生差异补丁对象,再将差异补丁对象应用到真实的DOM节点上去,于是完成了页面的渲染和更新。

传统的Diff算法时间复杂度达到了O(n^3),若要满足每次都可以整体刷新页面的目的,这种指数型的增长的性能开销是无法满足性能要求的,于是,Facebook的工程师对此进行了优化,通过制定diff策略将Diff算法的复杂度降低到了O(n)

Diff 策略

  • DOM节点跨层级的操作特别少,所以可以忽略不计
  • 拥有相同类的两个组件将会产生相似的树形结构,拥有不同类的两个组件将会产生不同的树形结构
  • 同一层级的一组子节点,他们可以通过uuid进行区分

Diff 粒度

由于DIFF的粒度不同,DIFF算法按照下面的顺序依次执行

  • Tree DIFF
  • Component DIFF
  • Element DIFF

打补丁

我们根据diff策略以及react diff中的比对算法将两个虚拟DOM通过深度优先遍历进行比较,如果有差异,就把所遍历到节点的索引值所对应的操作存储起来,也称为补丁对象(patches)

然后对真实的DOM再次经过深度优先遍历,补丁对象中的索引就会和DOM相对应,我们就完成了DOM的更新操作。

结语
互联网环境下,随时刷新交互页面是我们上网的常规操作,然而这一简单的操作却是多次算法优化的结果。DOM DIFF的底层原理挺复杂,如果有感兴趣的朋友,可以自行搜索相关文献,因为本文只是浅析,所以太多方面就不赘述了,如果本文有知识错漏的地方,也欢迎指正!虚心接收一切合理批评!😉

如果这篇文章有帮助到你对dom diff算法的理解,也希望您能为我点一个赞😃,答主是刚入门的前端小白,每一个赞都是我前进的动力,我会持续更新掘金的博客的🤗

以上就是详解react应用中的DOM DIFF算法的详细内容,更多关于react应用的DOM DIFF算法的资料请关注编程网其它相关文章!

--结束END--

本文标题: 详解react应用中的DOM DIFF算法

本文链接: https://www.lsjlt.com/news/123159.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 详解react应用中的DOM DIFF算法
    目录前言 什么是Virtual DOM? 使用Virtual DOM的原因 DOM 渲染页面的操作流程 Virtual DOM的优势如何将DOM用virtual DOM 来表...
    99+
    2022-11-12
  • react中的虚拟dom和diff算法详解
    虚拟DOM的作用 首先我们要知道虚拟dom的出现是为了解决什么问题的,他解决我们平时频繁的直接操作DOM效率低下的问题。那么为什么我们直接操作DOM效率会低下呢? 比如我们创建一个d...
    99+
    2022-11-12
  • React diff算法超详细讲解
    目录diff 算法介绍diff 策略tree diffcomponent diffelement diff结合源码看 diff整体流程新内容为 REACT_ELEMENT_TYPE新...
    99+
    2022-11-13
    React diff算法原理 React diff算法源码
  • React中的Diff算法你了解吗
    目录一、Diff算法的作用二、React的Diff算法  1、什么是调和?2、什么是React diff算法?3、diff策略4、tree diff:5、comp...
    99+
    2022-11-13
  • Vue3组件更新中的DOM diff算法示例详解
    目录同步头部节点同步尾部节点添加新的节点删除多余节点处理未知子序列移动子节点建立索引图更新和移除旧节点移动和挂载新节点最长递增子序列总结总结在vue的组件更新过程中,新子节点数组相对...
    99+
    2022-11-13
  • React diff算法面试考点超详细讲解
    目录前言diff算法的概念手写diff算法的过程前言 在前端工程上,日益复杂的今天,性能优化已经成为必不可少的环境。前端需要从每一个细节的问题去优化。那么如何更优,当然与他的如何怎么...
    99+
    2022-12-19
    React diff算法原理 React diff算法源码
  • 怎么在react中实现一个虚拟dom和diff算法
    这篇文章将为大家详细讲解有关怎么在react中实现一个虚拟dom和diff算法,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。虚拟DOM,见名知意,就是假的DOM,我们真实的DOM挂载在页面上...
    99+
    2023-06-14
  • React Diff算法不采用Vue的双端对比原因详解
    目录前言React 官方的解析Fiber 的结构Fiber 链表的生成React 的 Diff 算法第一轮,常见情况的比对第二轮,不常见的情况的比对重点如何协调更新位置信息小结图文解...
    99+
    2022-11-13
  • Vue的虚拟DOM和diff算法你了解吗
    目录什么是虚拟DOM?为什么需要虚拟DOM?总结在vue 中 数据改变 -> 虚拟DOM(计算变更)-> 操作DOM -> 视图更新 虚拟DOM: js执行速度比较...
    99+
    2022-11-13
  • 怎样深入理解vue中的虚拟DOM和Diff算法
    怎样深入理解vue中的虚拟DOM和Diff算法,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。真实DOM的渲染在讲虚拟DOM之前,先说一下真实DOM的渲染。浏览器真实DOM渲...
    99+
    2023-06-22
  • Vue中的虚拟DOM和Diff算法实例分析
    这篇文章主要介绍了Vue中的虚拟DOM和Diff算法实例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Vue中的虚拟DOM和Diff算法实例分析文章都会有所收获,下面我们一起来看看吧。简单介绍一下 虚拟DO...
    99+
    2023-06-29
  • Vue2 的 diff 算法规则原理详解
    目录前言算法规则diff 优化策略老数组的开始与新数组的开始老数组的结尾与新数组的结尾老数组的开始与新数组的结尾老数组的结尾与新数组的开始以上四种情况都没对比成功推荐在渲染列表时为节...
    99+
    2022-11-13
  • 一文详解Vue 的双端 diff 算法
    目录前言diff 算法简单 diff双端 diff总结前言 Vue 和 React 都是基于 vdom 的前端框架,组件渲染会返回 vdom,渲染器再把 vdom 通过增删改的 ap...
    99+
    2022-11-13
  • React使用refs操作DOM方法详解
    在react框架 甚至说是三大框架中都是不太支持大家直接去操作dom的 因为也没什么必要 当然也会有特殊情况 例如视频播放 强制动画 第三方插件的一些渲染或初始化 官方也给了我们对应...
    99+
    2022-11-13
    React操作DOM React refs操作DOM
  • 一文详解Vue3中简单diff算法的实现
    目录简单Diff算法减少DOM操作例子结论实现DOM复用与key的作用例子虚拟节点的key实现找到需要移动的元素探索节点顺序关系实现如何移动元素例子实现添加新元素例子实现移除不存在的...
    99+
    2022-11-13
  • Vue中的双端diff算法怎么应用
    这篇文章主要讲解了“Vue中的双端diff算法怎么应用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue中的双端diff算法怎么应用”吧!Vue 和 React 都是基于 vdom 的前端...
    99+
    2023-07-02
  • React的调和算法Diffing算法策略详解
    目录算法策略单节点diffing数组节点diffingkey值的使用要求算法策略 React的调和算法,主要发生在render阶段,调和算法并不是一个特定的算法函数,而是指在调和过程...
    99+
    2022-11-12
  • Vue2中的Diff算法怎么使用
    这篇文章主要介绍了Vue2中的Diff算法怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Vue2中的Diff算法怎么使用文章都会有所收获,下面我们一起来看看吧。为什么要用 Diff 算法虚拟 DOM因为...
    99+
    2023-07-05
  • 深入理解vue2中的VNode和diff算法
    虚拟dom和diff算法是vue学习过程中的一个难点,也是面试中必须掌握的一个知识点。这两者相辅相成,是vue框架的核心。今天我们再来总结下vue2中的虚拟dom 和 diff算法。(学习视频分享:vue视频教程)什么是 VNode我们知道...
    99+
    2022-11-22
    VNode diff算法 Vue vue.js
  • 怎么深入解析Vue3中的diff 算法
    今天给大家介绍一下怎么深入解析Vue3中的diff 算法。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。1.0  diff 无key子节点在处理被标记...
    99+
    2023-06-26
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作