虚拟dom
虚拟dom是react的核心特性,它让react的渲染性能更高效。
js正常操作dom,会引起整个页面回流重排,性能差。
使用虚拟dom,会用js对象先模拟dom的更新,比对出实际更新的dom进行局部更新。
- 执行过程:
- React组件配合 state 创建一个虚拟DOM树
- 根据虚拟DOM树,生成一个真正的 DOM 树,再渲染到页面中
- 当 state 或者 props 变化时,根据新的数据生成一个新的虚拟DOM树
- 将新旧虚拟 DOM 树进行对比,通过diff算法找到新旧虚拟DOM的差异点,最后将差异点更新到页面上
diff算法:
1、比较层级(tree diff),如果某节点不存在了,则连同该节点的后代全部删除,不再继续比较。
2、比较组件(component diff)
React对于组件的策略有两种方式,分别是类型相同和类型不同的组件
相同的直接继续比较组件内部的dom,不同的类型的会直接替换掉组件内部所有节点(可能虚拟DOM并没有任何变化,所以用户可以通过shouldComponentUpdate() 来判断是否需要更新)
3、比较节点(element diff),对于同一层级的子节点,通过唯一的key比较。如果更新的节点key在老集合里已存在,直接复用。没有的话,插入新节点
所以react不建议用index当key,因为增删等修改dom的操作,会导致index错乱,引发错误渲染的bug,就失去了diff算法的意义
合成事件
react有一套独特的事件机制,包括事件注册、合成、冒泡、派发等,这套机制称之为合成事件。
react合成事件不会直接绑在dom上,而是使用事件委托机制,将事件全部绑定在顶层root节点上。当组件挂载或卸载时,只需在root节点上增加或删除对应事件的监听。
合成事件的好处:
• 对事件进行归类,可以在事件产生的任务上包含不同的优先级
• 提供合成事件对象,抹平浏览器的兼容性差异
• 减少内存消耗,提升性能,不需要注册那么多的事件了,一种事件类型只在 Root上注册一次
原生事件先于React事件执行
JSX
在js里面写html是一件很舒服且效率很高的事情,而react通过jsx实现了。
要明白JSX的原理,需要先明白如何用 JavaScript 对象来表现一个 DOM 元素的结构
代码语言:javascript复制1 <div class="app" id="appRoot">
2 <h1 class="title">欢迎进入React的世界</h1>
3 <p>
4 React.js 是一个帮助你构建页面 UI 的库
5 </p>
6 </div>
7
8上面这个 HTML 所有的信息我们都可以用 JavaScript 对象来表示:
9
10 {
11 tag: "div",
12 attrs: { className: "app", id: "appRoot"},
13 children: [
14 {
15 tag: "h1",
16 attrs: { className: "title" },
17 children: ["欢迎进入React的世界"]
18 },
19 {
20 tag: "p",
21 attrs: null,
22 children: ["React.js 是一个构建页面 UI 的库"]
23 }
24 ]
25}
26
react打包编译的过程会把类似 HTML 的 JSX 结构转换成 JavaScript 的对象结构
主要通过React.createElement()实现转换过程
代码语言:javascript复制1//React.createElement` 会构建一个 JavaScript 对象来描述你 HTML 结构的信息
2//包括标签名、属性、还有子元素等
3React.createElement(
4 type, (必填,代表的是标签名,eg: ul)
5 [props], (选填,代表属性,像className什么的)
6 [...children] (选填,子节点,eg:要显示的文本内容 )
7)
8//举例:
9React.createElement("h1", {className: "main"}, "Hello React (method 2)");
示例:
代码语言:javascript复制1import React from "react";
2import ReactDOM from "react-dom";
3
4class App extends React.Component {
5 render() {
6 return (
7 <div className="app" id="appRoot">
8 <h1 className="title">欢迎进入React的世界</h1>
9 <p>React.js 是一个构建页面 UI 的库</p>
10 </div>
11 );
12 }
13}
14ReactDOM.render(<App />, document.getElementById("root"));
15
编译之后将得到这样的代码:
代码语言:javascript复制1import React from "react";
2import ReactDOM from "react-dom";
3class App extends React.Component {
4 render() {
5 return React.createElement(
6 "div",
7 {
8 className: "app",
9 id: "appRoot",
10 },
11 React.createElement("h1", { className: "title" }, "欢迎进入React的世界"),
12 React.createElement("p", null, "React.js 是一个构建页面 UI 的库")
13 );
14 }
15}
16
17ReactDOM.render(React.createElement(App), document.getElementById("root"));
想使用jsx有两种方式
- 在.jsx文件中引入React
- 配置babel,达成无需引入react就可以在.js中使用jsx