React的渲染过程

  • 如果是HTML标签则直接渲染真实DOM
  • 如果是JSX,则按以下流程进行
    1. 将JSX转换成 createElement 的代码
    2. 执行 createElement 创建虚拟DOM, 得到虚拟DOM树
    3. 根据虚拟DOM树在界面上生成真实DOM

JSX

1
2
3
4
<div>
<div><p>我是段落</p></div>
<div><span>我是span</span></div>
</div>

转换为 createElement 代码

1
2
3
4
5
6
React.createElement("div", null,
React.createElement("div", null,
React.createElement("p", null, "我是段落")),
React.createElement("div", null,
React.createElement("span", null, "我是span"))
);

生成虚拟DOM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
targetName: 'div',
children:[
{
targetName: 'div',
children:[
{
targetName: 'p'
}
]
},
{
targetName: 'div',
children:[
{
targetName: 'span'
}
]
}
]
}

Diff算法的原理

更新时为了避免,为了计算出 Virtual DOM 中真正变化的部分,并只针对该部分进行原生 DOM 操作,而非重新渲染整个页面。React 使用了 Diff 算法对虚拟 DOM 的变化进行比较,基本原则为:

  • 进行同层同位置的比较
  • 如果是相同类型的元素,记录变化
  • 如果是不同类型的元素,删除以前的,使用新的

Diff算法的优化

Diff算法虽然只进行同层同位置的比较,但也有一些优化:

  1. 同层节点之间相互比较,不会跨节点比较(tree diff);
  2. 拥有相同类的两个组件将会生成相似的树形结构,拥有不同类的两个组件将会生成不同的树形结构。(component diff);
  3. 可以通过唯一 key 来指定哪些节点在不同的渲染下保持稳定(element diff);