三、虚拟DOM与JSX

3.1 虚拟DOM

众所周知,DOM操作是Web交互的核心,但是它比大多数JS操作要慢得多,例如,假设您有一个包含十个项目的列表。您删除了第一项。大多数JavaScript框架都会重建整个列表。这是必要的工作十倍!只有一个项目更改,但其余九个被重建了以前的状态。重建列表对网络浏览器来说没什么大不了的,但是现代网站可以使用大量的DOM操作。效率低下的更新已成为一个严重的问题。

为了解决这个问题,React引入虚拟DOM。

  1. 虚拟DOM就是一个JS对象
    ​​​const virtualDom = {...}​​在React中,对于每个DOM对象,都有一个对应的虚拟DOM对象。虚拟DOM对象是DOM对象的轻量级副本
  2. 当您渲染JSX元素时,每个虚拟DOM对象都会更新。这看似效率非常低,但是cost微不足道,因为虚拟DOM可以更新的很快(由于他是一个普通的JS对象)。
  3. 虚拟DOM更新后,React将虚拟DOM与更新之前保存的虚拟DOM快照进行比较。通过将新的虚拟DOM与原来的虚拟DOM快照进行比较,React可以准确地计算出哪些虚拟DOM对象已更改。这个过程称为“差异”。
  4. 一旦React知道了哪些虚拟DOM对象已更改,React就会在真实的DOM上只更新这些对象,注意不是整体更新。
  5. 引入虚拟DOM大大的提高了效率,避免了不必要的修改, 大大提高了操纵性能。

3.1.1 创建方式

  • JSX方式(推荐)
//1.创建虚拟DOM
const VDOM = ( /* 此处一定不要写引号,因为不是字符串 */
<h1 id="title">
<span>Hello,React</span>
</h1>
)
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))
  • JS方式
//1.创建虚拟DOM
const VDOM = React.createElement('h1',{id:'title'},React.createElement('span',{},'Hello,React'))
//2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))

3.1.2 虚拟DOM与真实DOM的转换

两者之间的转化:

  1. React提供了一些API来创建一种 “特别” 的一般js对象:
  • ​const VDOM = React.createElement('xx',{id:'xx'},'xx')​
  • 上面创建的就是一个简单的虚拟DOM对象
  1. 虚拟DOM对象最终都会被React转换为真实的DOM
  2. 我们编码时基本只需要操作react的虚拟DOM相关数据, react会转换为真实DOM变化而更新界。

区别:

  • 虚拟DOM本质上是Object类型的对象
  • 虚拟DOM比较轻,真实DOM比较重。因为虚拟DOM是在React内部使用的,无需真实DOM上那么多的属性。因为操纵虚拟DOM的时候不需要在页面上进行绘制,所以操纵虚拟DOM要比直接操纵DOM快得多。

3.2 JSX

3.2.1 简介

  1. 全称:​​JavaScript XML​
  2. 是由React定义的一种类似于XML的JS扩展语法:
  • JS + XML
  • 本质是​​React.createElemnet(component, props, ...children)​​方法的语法糖

3.2.2 作用

简化创建虚拟DOM

3.2.3 语法

  1. 定义虚拟DOM时,不要写引号。
// 注意=后边没有引号。
const VDOM = (
<h2>Hello World!</h2>
)
  1. 标签中混入JS表达式时要用​​{}​​,(JS表达式时有返回值的)
const containerId = "AbAb";
const name = "Honyelchak";
const VDOM = (
<h2 id={containerId.toLowerCase()}>{name}</h2>
)
  • 扩展: JS表达式与JS语句(代码)的区别:
  • 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方。
  • ​a​​​、​​a + b​​​、​​test(1)​​​、​​arr.map(...)​​​、​​function test(){}​
  • JS语句:
  • ​if(){}​​​、​​for(){}​​​·、​​switch(){....}​
  1. 样式的类名指定不要用class,要用​​className​​。
// 虚拟DOM样式的类名属性名不能用class,这是由于为了避免和es6中的class(类)发生冲突。
const VDOM = (
<h2 className="container"> </h2>
)
  1. 内联样式,要用​​style={{key:value}}​​的形式去写。
const VDOM = (
<h2 style={{color:'red', font-size:'14px'}}></h2>
)
  1. 只有一个根标签
  2. 标签必须闭合
  3. 标签首字母
  • 若小写字母开头,则将该标签转为html中同名元素,若html中无该标签对应的同名元素,则报错。
  • 若大写字母 开头,react就去渲染对应的组件,若组件没有定义,则报错。

3.2.4 babel.js的作用

  1. 浏览器不能直接解析JSX代码, 需要babel转译为纯JS的代码才能运行
  2. 只要用了JSX,都要加上type=“text/babel”, 声明需要babel来处理
<script type="text/label"></script>

3.3 渲染虚拟DOM

3.3.1 语法

ReactDOM.render(virtualDOM, containerDOM)

3.3.2 作用

将虚拟DOM元素渲染到页面中的真实容器DOM中显示。

3.3.3 参数说明

  1. 参数一: 纯js或jsx创建的虚拟dom对象
  2. 参数二: 用来包含虚拟DOM元素的真实dom元素对象(一般是一个div),可以利用js操纵DOM的方法​​document.getElementById('container')​​;