5.虚拟DOM
# JSX
JSX是一种JavaScript语法的扩展。React使用它来描述用户界面长成什么样子。
JSX语法转化过程:在React代码执行之前,Babel将JSX编译为React API。React.creatElement作用:字面上是创造页面元素,实际上是创造Virtual DOM对象(JavaScript对象)的。然后React会将Virtual DOM转换为真实的DOM对象。最后将真实DOM对象显示在页面上。
<div className="container">
<h3>hello</h3>
<p>good</p>
</div>
// 编译为:
React.creatElement("div", {
className: "container",
children: [
/*#__PURE__*/ _jsx("h3", {
children: "hello"
}),
/*#__PURE__*/ _jsx("p", {
children: "good"
})
]
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# DOM操作问题
使用JavaScript频繁的操作DOM,更新效率低下,消耗性能。
列如假设你有包含是个项目的列表,你只更改了列表中的第一项,大多数JavaScript框架会重建整个列表,这比必要的工作要多十倍。更新效率低下已经成为严重问题,为了解决这个问题,React普及了一种叫做Virtual DOM的东西,Virtual DOM出现的目的就是为了提高JavaScript操作DOM对象的效率。
# Virtual DOM是什么
在 React 中,每个 DOM 对象都有一个对应的 Virtual DOM 对象,它是 DOM 对象的 JavaScript 对象表现形式,其实就是使用 JavaScript 对象来描述 DOM 对象信息,比如 DOM 对象的类型是什么,它身上有哪些属性,它拥有哪些子元素。
<div className="container">
<h3>Hello React</h3>
<p>React is great </p>
</div>
2
3
4
{
type: "div",
props: { className: "container" },
children: [
{
type: "h3",
props: null,
children: [
{
type: "text",
props: {
textContent: "Hello React"
}
}
]
},
{
type: "p",
props: null,
children: [
{
type: "text",
props: {
textContent: "React is great"
}
}
]
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Virtual DOM如何提升效率
精准找出发生变化的 DOM 对象,只更新发生变化的部分。
在 React 第一次创建 DOM 对象后,会为每个 DOM 对象创建其对应的 Virtual DOM 对象,在 DOM 对象发生更新之前,React 会先更新所有的 Virtual DOM 对象,然后 React 会将更新后的 Virtual DOM 和 更新前的 Virtual DOM 进行比较,从而找出发生变化的部分,React 会将发生变化的部分更新到真实的 DOM 对象中,React 仅更新必要更新的部分。
Virtual DOM 对象的更新和比较仅发生在内存中,不会在视图中渲染任何内容,所以这一部分的性能损耗成本是微不足道的。
<div id="container">
<p>Hello React</p>
</div>
2
3
<div id="container">
<p>Hello Angular</p>
</div>
2
3
const before = {
type: "div",
props: { id: "container" },
children: [
{
type: "p",
props: null,
children: [
{ type: "text", props: { textContent: "Hello React" } }
]
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
const after = {
type: "div",
props: { id: "container" },
children: [
{
type: "p",
props: null,
children: [
{ type: "text", props: { textContent: "Hello Angular" } }
]
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
# 创建虚拟DOM
在 React 代码执行前,JSX 会被 Babel 转换为 React.createElement 方法的调用,在调用 createElement 方法时会传入元素的类型,元素的属性,以及元素的子元素,createElement 方法的返回值为构建好的 Virtual DOM 对象。