首页 > 其他分享 >从虚拟dom知识无痛深入vue与react的原理

从虚拟dom知识无痛深入vue与react的原理

时间:2024-03-31 22:32:28浏览次数:19  
标签:vue render dom react 虚拟 数据

 我们都知道像vue、react都有用到虚拟dom,那么虚拟dom到底是什么?框架为什么不直接操作真实dom而要在中间要引入虚拟dom呢?vue和react的虚拟dom又有什么异同呢?我们就从虚拟dom开始讲起,再来逐步引入讲解vue与react的部分原理及其异同,这里会顺便讲解到数据驱动视图及视图驱动数据,顺便明白MVVM、MVC这两种模式,顺便引入相关的八股文知识点,好好阅读这篇文章你会不小心一下子就明白了一大堆知识Σ(っ °Д °;)っ

所谓的虚拟dom、真实dom到底是什么?

实际上,我们在html文件里写的标签即为真实dom(能直接被浏览器解析渲染在页面呈现相应元素)。而虚拟 dom 就是一个普通的 js 对象,这个对象描述了界面的渲染内容虚拟dom与真实dom可以一一对应。如图:

//真实dom
<div id="app">
  <p class="text">木鱼</p>
</div>
//虚拟dom本质就是一个js对象,用来描述界面渲染内容,上述真实dom对应的虚拟dom结构如下:
{
  tag: 'div',
  props: {
    id: 'app'
  },
  chidren: [
    {
      tag: 'p',
      props: {
        className: 'text'
      },
      chidren: [
        '木鱼'
      ]
    }
  ]
}

虚拟dom的作用:

如果没有虚拟dom:作为通用框架,很难去预知数据跟界面之间到底是如何对应的(比如一个数据变了,框架不知道是界面哪个区域发生变动,数据是数据,界面是界面,框架能修改数据,也能通过render函数让界面重新渲染,但框架无法确定数据影响界面的具体区域),所以在没有虚拟 dom 的情况下,框架只能在数据发生变化了就直接将整个界面重新生成一次,这样没有发生变化的元素也会重新生成一遍,如此操作真实 dom 的代价就非常昂贵,会触发到浏览器的重排重绘让浏览器对整个页面所有元素都重新渲染,就会严重引发效率问题。

为了减少对真实 dom 无意义的操作,因此不得不引入虚拟 dom。当数据变化之后,由于框架无法知道数据与界面的一一对应关系,不知道界面哪个区域要更新,而全量生成真实dom导致的渲染代价较大,既然要全量生成,框架就选择全量生成虚拟 dom(虚拟dom是 js 对象,给 js 对象属性赋值修改属性值、改动对象结构,并不涉及界面,仅仅只是修改一个对象属性而已,效率自然是非常高的),然后通过跟之前的虚拟 dom 进行对比,找到有差异的虚拟dom节点,改动该虚拟节点所对应的真实 dom即可(注意前面提过虚拟dom与真实dom可以一一对应,如此,真实dom就无需全量生成渲染,框架仅需根据虚拟dom对比后的结果做对应的节点更新即可。

除了以上情况,框架引入虚拟dom还有第二个原因,就是建立了一个抽象层。特别是像 react 这种框架,它在设计之时并没有将自己定位为一个页面级别应用框架,而是把自己定位为一个 UI 库(UI 表示用户界面,而用户界面不一定是网页,也可能是移动端、桌面应用程序等,而不同平台差异很大,我们平时说的 dom 通常是指在页面应用中的,而像小程序、移动端 app、桌面应用都没有所谓的 dom),框架为了消除平台之间的差异,于是抽象了一个UI的表达方式,它使用一个普通对象(即虚拟 dom)来表达 UI 界面,然后根据不同的平台去具体生成真实的界面,即建立了一个抽象层,也就是用一套虚拟 dom,可以对接不同平台的渲染逻辑,实现一次编码多端运行

虚拟dom树在框架中的存在形式

vue中的虚拟dom

  • vue 是怎么得到虚拟 dom 树的呢?
  • 实际上是 vue 有配置一个 render 函数,vue 运行了 render 函数返回的结果就是虚拟 dom(这个 render 函数有一个参数 h,h是个函数,h传入一个代表标签名和标签内容的参数,即可生成一个虚拟 dom,标签内容可再继续嵌入 h 函数表示其子节点信息)当改动数据后,render 依赖了这个被 vue 监听的,则会再执行一次 render 函数响应式,具体原理我在这篇文章描述过《关于Vue的数据响应式》原文链接:http://t.csdnimg.cn/KYlEg
  • 而 vue 给我们提供了模板,我们在Vue上是通过Vue的模板(在template标签或属性里写)书写HTML信息,而vue模板上的内容实际上并不是真实 dom,vue 会根据模板编译成 render 方法逻辑是看是否有 render 方法,有的话则略过模板内容直接把 render 方法的返回结果作为虚拟节点树。如果没有 render 方法,则查找模板,即 template 这个配置,把模板编译成 render 方法;如果模板 template 这个配置也没有的话,它会查找 el 这个配置对应的元素,将这个元素直接作为模板,再将模板编译成 render,再通过 render 生成虚拟节点树,才能进行渲染真实节点。由于树形结构只有一个根节点(一个根节点才能保证是一棵树),因此 vue 会要求模板也必须只有个根节点,这样编译成 render 函数生成的虚拟节点数才是单根的。

react中的虚拟dom

  • react 又是怎么得到虚拟 dom 树的呢?
  • 无论是使用react 的 class 或 function 写法, 本质都是生成 render 函数,其返回结果为描述页面信息结构的jsx语法。
  • react 是使用 jsx 语法,在组件中直接编写虚拟 dom 结构,然后通过 Babel 等工具将其转换为 JavaScript 代码。
  • jsx其实是 createElement()方法的语法糖,jsx 语法会被@babel/preset-react 插件编译为 createElement()方法,而 createElement()方法会返回 react 元素,也就是虚拟dom对象(react 元素就是一个 js 对象,用来描述真实 dom 的内容,其本质也就是虚拟 dom,只是在不同应用场景叫法不同)

vue与react的虚拟dom及其应用形式的对比

本质上vue与react虚拟dom并没有什么区别。vue 和 react 本质都是用 js 对象来模拟真实 dom(二者仅仅是让程序员书写页面结构的形式以及将其编译为虚拟dom的方式不同。但无论是 vue 的模板写法还是 react 的 class 或 function 写法, 最后都是生成 render 函数,而 render 函数会执行返回一个描述页面信息结构的对象,也就是虚拟 dom,本质上是棵树),然后都是通过对虚拟 dom 进行 diff 算法来最小化更新真实 dom,从而减少不必要的性能损耗(其中 diff 算法的优化思路基本相同:tag 不同则视为不同节点;只比较同一层级,不跨级比较;同一层级节点用 key 唯一标识,tag 和 key 都相同则视为同一节点[所以无论是 react 还是 vue,在写动态列表时都需要设置一个唯一值 key,这样 diff 算法处理时才能性能最大化]

标签:vue,render,dom,react,虚拟,数据
From: https://blog.csdn.net/didadidadidadida/article/details/137136576

相关文章

  • vue-路由详解
    路由vue-router1.对路由的理解:vue的一个插件库,专门用来实现SPA应用2.对SPA应用的理解:1.单页web应用2.整个应用只有一个完整的页面(index.html)3.点击页面中的导航链接不会刷新页面,只做页面的局部更新4.数据需要通过ajax请求获取3.什么是路由?1.......
  • React Native简介和环境配置,差点挂在第四面
    ReactNative目前需要NodeJS5.0或更高版本。本文发布时Homebrew默认安装的是最新版本,一般都满足要求。brewinstallnode安装完node后建议设置npm镜像以加速后面的过程(或使用科学上网工具)。注意:不要使用cnpm!cnpm安装的模块路径比较奇怪,packager不能正常识别!npmconfig......
  • Vite + Vue3 项目的创建 ,启动 ,停止
    第一步:使用命令行创建工程在磁盘的合适位置上,创建一个空目录用于存储多个前端项目用vscode打开该目录在vocode中打开命令行运行如下命令npmcreatevite@latest第一次使用vite时会提示下载vite,输入y回车即可,下次使用vite就不会出现了注意:选择vue+JavaScript选项即可......
  • 多目标应用:基于非支配排序的蜣螂优化算法(Non-Dominated Sorting Dung beetle optimize
    一、柔性作业车间调度问题柔性作业车间调度问题(FlexibleJobSchedulingProblem,FJSP)的描述如下:n个工件{J,J......
  • 数据下钻--vue+springboot+echarts
    今天下午整了下数据下钻直接上成果: 然后左边可以选范围:左边调范围,然后对应的会显示那些省份满足条件。 然后就是鼠标悬停在某个省份,就显示相应数量: 然后可以点击对应省份进行下钻到市然后可以继续下钻到县:  同样的呢,市和县都可以向省一样那样显示范围和调试: ......
  • DOM 节点遍历:掌握遍历 XML文档结构和内容的技巧
    遍历是指通过或遍历节点树遍历节点树通常,您想要循环一个XML文档,例如:当您想要提取每个元素的值时。这被称为"遍历节点树"。下面的示例循环遍历所有<book>的子节点,并显示它们的名称和值:<!DOCTYPEhtml><html><body><pid="demo"></p><script>varx,i,xmlDoc;va......
  • react路径别名@配置
    首先下载包craconpmi-D @craco/craco1.路径解析在项目根目录下创建craco.config.js配置如下2.vscode识别配置在项目根目录下创建jsconfig.json,配置如下3. package.json将start和build的内容改成craco,重启项目 ......
  • 基于ssm+vue.js的酒店预约及管理系统附带文章和源代码设计说明文档ppt
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我成功案例代码参考数据库参考源码获取前言......
  • 基于ssm+vue.js的校园招聘系统附带文章和源代码设计说明文档ppt
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我成功案例代码参考数据库参考源码获取前言......
  • 基于ssm+vue.js的宠物医院管理系统附带文章和源代码设计说明文档ppt
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我成功案例代码参考数据库参考源码获取前言......