React进阶 - 13(说一说 React 中的虚拟 DOM)

本章内容

目录

    • 一、为什么需要"虚拟DOM"
    • [二、虚拟 DOM" 带来的希望](#二、虚拟 DOM“ 带来的希望)
    • [三、虚拟 DOM" 的优势(性能大幅度提升 & 跨端应用)](#三、虚拟 DOM“ 的优势(性能大幅度提升 & 跨端应用))

上一节我们讲了 statepropsrender函数的关系,本节内容开始了解 React中的"虚拟 DOM" 相关知识。

一、为什么需要"虚拟DOM"

  • 上篇文章,我们知道:当组件的 state或者 props变化时,render函数会重新知己,界面也重新被渲染。
  • 然而,我们要知道,页面的重新渲染这个过程是非常耗性能的。
  • 假设没有 React, 我们要实现数据变化界面也随着变化,通常可以这么做
text 复制代码
方式一:
1、定义一个 state 数据
2、定义一个 "JSX模版"
3、将"数据+JSX模版"结合,生成真实 DOM 来显示
4、当数据变化时
5、"数据+JSX模版"相结合,生成真实DOM,替换原始 DOM
6、如此往复循环 4、5步骤

方式二:(对方式一进行优化下,不直接替换旧的 DOM,只替换变化的数据节点)
1、定义一个 state 数据
2、定义一个 "JSX模版"
3、将"数据+JSX模版"结合,生成真实 DOM 来显示
4、当数据变化时
5、"数据+JSX模版"相结合,生成真实 DOM
6、新的 DOM 和旧 DOM比对,找到只变化的节点
7、用新 DOM 变化的节点替换旧 DOM 变化处的节点
8、如此往复循环 5、6、7步骤


方式二相对于方式一的步骤增加了,但是性能会有所提升(局部替换比整体替换消耗的性能更少),但是方式二的比较过程同样耗费了些性能,这样来看,性能也没提升多少

二、虚拟 DOM" 带来的希望

基于上述的痛点,React提出了"虚拟 DOM"的方案。也就是方式三:

  • 1、定义一个 state数据
js 复制代码
this.state = {
  content: 'hello'
}
  • 2、定义一个 JSX 模版
js 复制代码
render() {
 return (
  <div id="d1">
    <span>{content}</span>
  </div>
 )
}
  • 3、"数据+JSX模版"结合,React底层会调用 React.createElement()接口,将 JSX 模版变成一个原始的"虚拟DOM"(虚拟DOM 本质是一个数组形式的 JS对象,用它来描述"真实的DOM")
text 复制代码
虚拟 DOM 格式:[标签名,标签属性,标签的子节点]

注意如果标签子节点又是一个完整的 DOM,那么还是遵循 "[标签名,标签属性,标签的子节点]" 的格式

那将 2中的"JSX模版"转为"JS对象"的底层实现。运行后发现,我们可以通过 React.createElement()来实现 JSX的功能。唯一的缺点就是很复杂,所以这也是为什么 JSX存在的原因,它是一个更加简便好用的方式

js 复制代码
// 1、注释掉这里,改用下面的 React.createElement方式实现
// render() {
//  return (
//   <div id="d1">
//     <span>{content}</span>
//   </div>
//  )
// }

// 2、使用 React.createElement方式实现上面注释的功能
render() {
 // 我们将"JSX 模板"用 craeteElement 方法来改写,其接收 3 个参数依次是:元素的标签名、标签的属性、元素的children 子节点
 return React.createElement("div", {id: "d1", React.createElement("span", {}, "hello")})
}

上面生成的"虚拟DOM"为:["div", {id: "d1"}, ["span", {}, "hello"]]

  • 4、根据上面的"虚拟DOM"生成"真实DOM"
html 复制代码
 <div id="d1">
    <span>{content}</span>
  </div>
  • 5、当数据 state变化
js 复制代码
this.state = {
  content: 'hello world'
}
  • 6、重复 3步骤,生成新的"虚拟DOM": ["div", {id: "d1"}, ["span", {}, "hello world"]]

  • 7、比较"旧的虚拟DOM"和"新的虚拟DOM",找到 span中的内容是有变更的

  • 8、直接操作 DOM,改变 span里的内容

三、虚拟 DOM" 的优势(性能大幅度提升 & 跨端应用)

  • "虚拟DOM"本质上是用 JS生成的一个 JS对象,这个转变消耗的性能较少。如果直接使用 JS生成一个 DOM元素,那么它是会底层调用 Web ApplicationAPI,性能消耗极大

  • 然后两个"虚拟DOM"之间比对,本质是 js对象的比对,其底层使用的"Diff算法"是不怎么消耗性能的。如果直接把两个"真实 DOM"进行比对,其性能消耗极大

  • "JS 对象"不仅可以让"浏览器"识别,在原生应用(Android IOS)上也可以(注意:"原生应用"里不存在 DOM的概念,所以真实的 DOM在原生应用中不被识别,无法使用),因此,有了"虚拟DOM"后,我们用它生成一些原生组件。

  • 这样的话,在复用"state"、"JSX模版"等代码优势下,让"虚拟DOM"在不同"端"中进行转化:网页端转化为"真实DOM",原生应用中转化为原生的"组件"

到此,本章内容结束!

相关推荐
陈王卜2 分钟前
django+boostrap实现发布博客权限控制
java·前端·django
景天科技苑10 分钟前
【vue3+vite】新一代vue脚手架工具vite,助力前端开发更快捷更高效
前端·javascript·vue.js·vite·vue项目·脚手架工具
石小石Orz19 分钟前
Three.js + AI:AI 算法生成 3D 萤火虫飞舞效果~
javascript·人工智能·算法
小行星12521 分钟前
前端预览pdf文件流
前端·javascript·vue.js
join822 分钟前
解决vue-pdf的签章不显示问题
javascript·vue.js·pdf
小行星12528 分钟前
前端把dom页面转为pdf文件下载和弹窗预览
前端·javascript·vue.js·pdf
疯狂的沙粒30 分钟前
如何在 React 项目中应用 TypeScript?应该注意那些点?结合实际项目示例及代码进行讲解!
react.js·typescript
Lysun00137 分钟前
[less] Operation on an invalid type
前端·vue·less·sass·scss
土豆湿44 分钟前
拥抱极简主义前端开发:NoCss.js 引领无 CSS 编程潮流
开发语言·javascript·css
J总裁的小芒果1 小时前
Vue3 el-table 默认选中 传入的数组
前端·javascript·elementui·typescript