React原理 - React Virtual DOM 原理

目录

扩展学习资料

 Virtual DOM 是什么【虚拟dom】

React渲染

Virtual DOM VS 原生DOM【vDom是否比原生Dom更高效】

Virtual DOM数据结构

Virtaual DOM Diff【虚拟dom前后比对,更新不同dom的算法】

源码解读

react源码组织方式:

React Stack Reconciler【react 栈 协调】

react v15.6.2 源码

练习


扩展学习资料

名称

链接

备注

Virtual DOM 定义

Virtual DOM and Internals – React

英文

Virtual DOM Node

Mithril.js

英文

VDom与 DOM 的区别

The difference between Virtual DOM and DOM - React Kung Fu

英文

React性能优化:Virtual Dom原理浅析

[译] React性能优化:Virtual Dom原理浅析 - 掘金

[译] Virtual Dom 和 Diff 算法

[译] Virtual Dom 和 Diff 算法在 React 中是如何工作的? - 掘金

  • 比较前一个的内部实例与下一个内部实例
  • 更新内部实例Virtual DOM(JavaScript对象) 中的组件树结构。
  • 仅更新存在实际变化的节点及其子节点的真实DOM。

 Virtual DOM 是什么【虚拟dom】

虚拟DOM(virtualdom,VDOM)是一个编程概念,将UI的“虚拟”表示形式保存在内存中,并通过ReactDOM之类的库渲染成“真实”的DOM,这个过程叫做协调。

virtual dom将UI节点抽象成js对象

UI节点抽象:Virtual Dom对HTML Dom的抽象

Learn Once,Write Anywhere:因为提供了对HTML DOM的抽象,所以在Web开发中,通常不需要去调用DOM API。也是因为抽象,所以React也可以开发Native(React Native)。【跨平台性】

Virtual Dom构建UI

构建UI:以我们经常见的Web开发为例,来看下React是怎么通过Virtual DOM渲染成HTML元素的。

React渲染

class App extends Component {
    state = {
        text: 'Virtual DOM',    
    }
    
    render() {
        const {text} = this.state;
        render (
            <div>{text}</div>        
        )    
    }
}

通过Virtual DOM 渲染页面

很简单的例子,渲染state遍历text的值。

可以看到React是通过render方法渲染Virtual DOM(这里不考虑优化),从而绘制出真实DOM。意味着,每次修改了state的值就会执行render方法。

Virtual DOM是HTML DOM的映射,基本结构大致是一样的

 

Virtual DOM VS 原生DOM【vDom是否比原生Dom更高效】

  • 原生DOM更新
    • DOM API 调用更新UI
  • Virtual DOM更新
    • 每次render都会产生一份新的‘react dom’
    • Virtual DOM要对新旧‘react dom’进行比较,从而确定在旧‘dom’的基础上进行多少变更
    • 确定最优的变更策略之后调用DOM API更新UI

Virtual DOM渲染成HTML,在流程上会比原生DOM操作多几个步骤

实际应用中,页面的操作逻辑会比较复杂频繁,多次频繁操作Dom会导致页面重绘,页面重绘是影响页面性能的关键指标,造成卡顿。react在内部已经做了考虑,所以说会比原生Dom更加高效

Virtual DOM数据结构

对UI节点抽象

在Virtual DOM中,对HTML节点进行抽象。用JS对象的形式表示HTML。

改变了过去对HTML节点的理解。

呈现在用户面前的页面就是一个复杂的递归对象。

const globaldom = {
    tagName: 'html',
    children: [
        {
            tagName: 'head',        
        }, {
            tagName: 'body',
            children: [{
                tagName: 'div',
                attributes: {
                     className: 'test'               
                }            
            }]        
        }    
    ]
}

Virtaual DOM Diff【虚拟dom前后比对,更新不同dom的算法】

  • Virtual DOM如何提高性能【高效更新】
  1. 我们将render产生的Virtual DOM简称‘Vdom’;
  2. 通常调用setState方法触发Vdom更新;
  3. 通过对比新旧‘Vdom’,确定最优实现新‘Vdom’所需的操作;
  • Virtual DOM Diff 的层次
    • 组件级别比较
    • 元素级别比较

HTML DOM是个完整的树,常规树遍历的时间复杂度是n³,正是vdom对HTMLdom节点层次的划分,使得HTML树在Vdom中遍历的时间复杂度降为n0这也是Vdom高效的原因之一。

Virtual DOM Diff是体现其性能/维护性的重要过程

  • Component Diff【组件级比较】:不同就直接开始替换组件及它的子组件(不再比对子组件)

 

  • 元素级别的比较【三个层面:创建、移动、删除】

  • 创建子节点

 react源码:diff 添加子节点

createChild: function (child, afterNode, mountImage) {
    return makeInsertMarkup(mountImage, afterNode, child._mountIndex);
},
  • 删除子节点

 react源码:diff删除子节点

removeChild: function (child, node) {
    return makeRenove(child, node);
},
  • 移动节点

 react源码:diff移动子节点【截取片段】

// 老节点和新节点相等,说明是移动
if(prevChild === nextChild) {
    updates = enqueue(updates, this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex));
    lastIndex = Math.max(prevChild._mountIndex, lastIndex);
    prevChild._mountIndex = nextIndex;
}
moveChild: function (child, afterNode, toIndex, lastIndex) {
    // 原节点所在的挂载顺序数 < 更新后所在的顺序数
    if (child._mountIndex < lastIndex) {
        return makeMove(child, afterNode, toIndex);    
    } else {
        // 不移动它,而是把它后面应该在前面的节点移动到它前面去    
    }
}

我们应该规避如图示例,将最后一个节点移动到最前面。【这种操作显得不那么高效】

react源码比较复杂,不直观【相对开发来说】;

react的移动、创建、删除并不是在react包中实现的,而是在react dom这个包中实现的。【动态挂载技术】

 

源码解读

react源码组织方式:

  1. 动态注入:react包源码中只是声明变量并没有实现,实现是写在react dom包中【考虑到多平台,把公共部分react抽了出来,react dom是个render器; react native是另一个render器;如公共方法setState,react中就只是定义;实现是在react dom、react native中实现各自的。】
  2. react dom中源码:比如渲染HTML节点的时候,采用的是嵌套循环【渲染、更新、比较】(因为HTML树本身就是一种循环嵌套的方式)

React Stack Reconciler【react 栈 协调】

render -> Virtual DOM Diff->commit【更新】

总结

1.Virtual DOM不仅仅是抽象了HTML Dom操作,更多的是抽象了UI节点,其次带来一种编程理念:数据驱动视图。

Virtual DOM本身的抽象性也使得跨平台成为了可能。

2.如何看待VDom比原生Dom更加高效?

(1)高效的Diff算法实现更新

(2)可维护性和编程思维方面

react v15.6.2 源码

react v15.6.2.zip

练习

阅读React源码  React v15.6.2 重点阅读 react-dom ReactMultiChild.js(react-dom/lib/ReactMultiChild.js) 源码。

产出:

  • 一份 Virtual DOM 与 HTML DOM 的对比图;
  • 一份分析 Element 比较的流程图。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/88145.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv5基础知识入门(7)— NMS(非极大值抑制)原理解析

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。NMS是指非极大值抑制&#xff08;non maximum suppression&#xff09;&#xff0c;它是一种常用于物体检测任务的算法。在物体检测中&#xff0c;通常会有多个预测框&#xff08;bounding box&#xff09;被提议出来&…

开始MySQL探索——数据库概述

计算机语言 计算机语言概述 计算机语言&#xff08;Computer Language&#xff09;可以简单的理解为一种计算机和人都能识别的语言。 机器语言 汇编语言 高级语言 机器语言 汇编语言 高级语言 SQL语言基础 SQL的概述 SQL全称&#xff1a;Structured Query Language&…

Aspose.Tasks for .NET V23Crack

Aspose.Tasks for .NET V23Crack 改进了大型项目的内存占用。 添加了API&#xff0c;允许您在应用程序无法访问系统字体文件夹时指定用户的字体文件夹。 Aspose.Tasksfor.NET是处理MicrosoftProject文件的可靠的项目管理API。API支持在不依赖Microsoft Project的情况下读取、写…

平安私人银行慈善沙龙广州站:善财传承公益有道,广州分行聚爱同行

近年来&#xff0c;平安私人银行将慈善作为客户服务的王牌权益之一&#xff0c;激发和满足客户公益慈善心愿&#xff0c;打造财富人群和困境人群的桥梁&#xff0c;并链接公益机构等专业组织&#xff0c;深度挖掘金融赋能慈善的多种可能性&#xff0c;让财富通过慈善事业释放出…

在router中使用pinia、在组件外使用pinia时 报错没有激活pinia

getActivePinia was called with no active Pinia. Did you forget to install pinia? 我想在路由守卫中使用store中部的数据&#xff0c;但是拿不到仓库&#xff0c;提示pinia没激活 解决方案&#xff1a;借鉴vben-admin 在每个模块中都把pinia和当前的仓库绑定一份暴漏出去…

ARM--day5(C语言点灯实验、总线、串口通信信息、串口通讯协议)

函数分装实现点灯 gpio.c: #include "gpio.h" //函数功能&#xff1a;GPIO引脚初始化操作 //参数1&#xff1a;GPIO组号 //参数2&#xff1a;引脚编号 //参数3&#xff1a;初始化内容 void hal_gpio_init(volatile gpio_t*gpiox,unsigned int pin,gpio_init_t* ini…

net start Mysql 启动服务时 ,显示“Mysql服务正在启动 Mysql服务无法启动 服务没有报告任何错误

一、问题 有时候&#xff0c;输入net start Mysql 启动服务时 mysql>net start Mysql 显示 Mysql服务正在启动 Mysql服务无法启动 服务没有报告任何错误 二、原因 由于mysql的默认端口是3306&#xff0c;因此在启动服务的时候&#xff0c;如果此端口被占用&#xff0c;就会出…

VB.NET通过VB6 ActiveX DLL调用PowerBasic及FreeBasic动态库

前面说的Delphi通过Activex DLL同时调用PowerBasic和FreeBasic写的DLL&#xff0c;是在WINDOWS基础平台上完成的。 而 .NET平台是架在WINDOWS基础平台之上的&#xff0c;它的上面VB.NET或C#等开发的APP程序&#xff0c;下面写一下用VB.NET&#xff0c;通过VB6注册的Activex DLL…

Ubuntu20.04安装软件报错:The following packages have unmet dependencies

Ubuntu20.04更换阿里云源后安装软件都会报错&#xff1a;The following packages have unmet dependencies 查看资料&#xff0c;大概是ubuntu本身的源比较版本较老&#xff0c;而阿里云的源比较新&#xff0c;因此版本不匹配造成依赖的库不匹配&#xff0c;所以只要将阿里云的…

vue 简单实验 数据更新

1.代码 <script src"https://unpkg.com/vuenext" rel"external nofollow" ></script> <div id"counter">Counter: {{ counter }} </div> <script> const Counter {data() {return {counter: 5}},mounted() {set…

基于Jenkins CICD的代码发布与回滚-------从小白到大神之路之学习运维第87天

第四阶段提升 时 间&#xff1a;2023年8月24日 地 点&#xff1a;2304教室 授课人&#xff1a;李凤海 参加人&#xff1a;全班人员 内 容&#xff1a; 基于Jenkins CICD的代码发布与回滚 目录 一、案例概述 二、案例知识点 三、案例环境 &#xff08;一&#xff0…

PHP“牵手”拼多多商品详情数据获取方法,拼多多API接口批量获取拼多多商品详情数据说明

拼多多商品详情接口 API 是开放平台提供的一种 API 接口&#xff0c;它可以帮助开发者获取拼多多商品的详细信息&#xff0c;包括商品的标题、描述、图片等信息。在拼多多电商平台的开发中&#xff0c;拼多多详情接口 API 是非常常用的 API&#xff0c;因此本文将详细介绍拼多多…

领域建模之数据模型设计方法论

本文通过实际业务需求场景建模案例&#xff0c;为读者提供一种业务模型向数据模型设计的方法论&#xff0c;用于指导实际开发中如何进行业务模型向数据模型转化抽象&#xff0c;并对设计的数据模型可用性、扩展性提供了建议性思考。通过文章&#xff0c;读者可以收获到业务模型…

POI groupRow 折叠分组,折叠部分不显示问题

折叠组是什么&#xff1f;如图就是用POI 实现的&#xff0c;代码很简单&#xff1a;sheet.groupRow(开始行&#xff0c;结束行)即可 但是万万没想到&#xff0c;最终实现出的结果&#xff0c;合并的组&#xff0c;有一部分并没有渲染出来&#xff0c;如下图&#xff1a; 因为我…

线性代数的学习和整理9(草稿-----未完成)

3.3 特征值和特征向量是什么&#xff1f; 直接说现在&#xff1a;特征向量这个块往哪个方向进行了拉伸&#xff0c;各个方向拉伸了几倍。这也让人很容易理解为什么&#xff0c;行列式的值就是特征值的乘积。 特征向量也代表了一些良好的性质&#xff0c;即这些线在线性变换后…

基于GPT-4和LangChain构建云端定制化PDF知识库AI聊天机器人

参考&#xff1a; GitHub - mayooear/gpt4-pdf-chatbot-langchain: GPT4 & LangChain Chatbot for large PDF docs 1.摘要&#xff1a; 使用新的GPT-4 api为多个大型PDF文件构建chatGPT聊天机器人。 使用的技术栈包括LangChain, Pinecone, Typescript, Openai和Next.js…

图论基础和表示(Java 实例代码)

目录 图论基础和表示 一、概念及其介绍 二、适用说明 三、图的表达形式 Java 实例代码 src/runoob/graph/DenseGraph.java 文件代码&#xff1a; src/runoob/graph/SparseGraph.java 文件代码&#xff1a; 图论基础和表示 一、概念及其介绍 图论(Graph Theory)是离散数…

基于Python的图书馆大数据可视化分析系统设计与实现

博主介绍&#xff1a;✌csdn特邀作者、博客专家、java领域优质创作者、博客之星&#xff0c;擅长Java、微信小程序、Python、Android等技术&#xff0c;专注于Java、Python等技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; …

【Apollo学习笔记】——规划模块TASK之LANE_CHANGE_DECIDER

文章目录 前言LANE_CHANGE_DECIDER功能简介LANE_CHANGE_DECIDER相关配置LANE_CHANGE_DECIDER总体流程LANE_CHANGE_DECIDER相关子函数PrioritizeChangeLaneUpdateStatusIsClearToChangeLaneHysteresisFilter 参考 前言 在Apollo星火计划学习笔记——Apollo路径规划算法原理与实…

springboot使用properties

一、方式1&#xff1a; 1.1.配置类&#xff1a; package cn.zyq.stater.config;import cn.zyq.stater.bean.User4; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework…