jsx本质
bable.js作用
浏览器不能直接解析jxs代码,需要bable转译为纯JS代码才能运行
只要用了JXS,都要加上type=“text/bable”,声明需要bable来处理
JSX 代表 Objects
实际上,jsx 仅仅只是 React.createElement(component, props, …children) 函数的语法糖。
Babel 转译器会把 JSX 转换成一个名为 React.createElement() 的方法调用。
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
//两种代码的作用是完全相同的:
我们知道默认jsx是通过babel帮我们进行语法转换的,所以我们之前写的jsx代码都需要依赖babel。
- 可以在babel的官网中快速查看转换的过程:https://babeljs.io/repl/#?presets=react
还有一种办法是我们自己来编写React.createElement代码:
class App extends React.Component {
constructor(props) {
render() {
/*#__PURE__*/
const result = React.createElement("div", {
className: "app"
}, /*#__PURE__*/React.createElement("div", {
className: "header"
}, /*#__PURE__*/React.createElement("h1", {
title: "\u6807\u9898"
}, "\u6211\u662F\u7F51\u7AD9\u6807\u9898")), /*#__PURE__*/React.createElement("div", {
className: "content"
}, /*#__PURE__*/React.createElement("h2", null, "\u6211\u662Fh2\u5143\u7D20"), /*#__PURE__*/React.createElement("button", {
onClick: e => console.log("+1")
}, "+1"), /*#__PURE__*/React.createElement("button", {
onClick: e => console.log("+1")
}, "-1")), /*#__PURE__*/React.createElement("div", {
className: "footer"
}, /*#__PURE__*/React.createElement("p", null, "\u6211\u662F\u7F51\u7AD9\u7684\u5C3E\u90E8")));
return result;
}
}
ReactDOM.render(React.createElement(App, null) , document.getElementById("app"));
上面的整个代码,我们就没有通过jsx来书写了,界面依然是可以正常的渲染。
另外,在这样的情况下,你还需要babel相关的内容吗?不需要了
- 所以,type="text/babel"可以被我们删除掉了;
- 所以,可以被我们删除掉了;
虚拟DOM
我们通过 React.createElement 最终创建出来一个 ReactElement对象:
这个ReactElement对象是什么作用呢?React为什么要创建它呢?
- 原因是React利用ReactElement对象组成了一个JavaScript的对象树;
- JavaScript的对象树就是大名鼎鼎的虚拟DOM(Virtual DOM);
而ReactElement最终形成的树结构就是Virtual DOM;
整体的转换过程如下:
jsx --> ReactElement对象 --> 真实DOM
为什么采用虚拟DOM?
- 很难跟踪状态发生的改变:原有的开发模式,我们很难跟踪到状态发生的改变,不方便针对我们应用程序进行调试;
- 操作真实DOM性能较低:传统的开发模式会进行频繁的DOM操作,而这一的做法性能非常的低;
DOM操作性能非常低:
首先,document.createElement本身创建出来的就是一个非常复杂的对象;
- https://developer.mozilla.org/zh-CN/docs/Web/API/Document/createElement
其次,DOM操作会引起浏览器的回流和重绘,所以在开发中应该避免频繁的DOM操作
这里我们举一个例子:
比如我们有一组数组需要渲染:[0, 1, 2, 3, 4],我们会怎么做呢?
<ul>
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
后来,我们又增加了5条数据:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for (var i=5; i<10; i++) {
var li = document.createElement("li");
li.innerHTML = arr[i];
ul.appendChild(li);
}
上面这段代码的性能怎么样呢?非常低效
-
因为我们通过 document.createElement 创建元素,再通过 ul.appendChild(li) 渲染到DOM上,进行了多次DOM操作;
-
对于批量操作的,最好的办法不是一次次修改DOM,而是对批量的操作进行合并;(比如可以通过DocumentFragment进行合并);
虚拟DOM帮助我们从命令式编程转到了声明式编程的模式
React官方的说法:Virtual DOM 是一种编程理念。
在这个理念中,UI以一种理想化或者说虚拟化的方式保存在内存中,并且它是一个相对简单的JavaScript对象,我们可以通过ReactDOM.render让 虚拟DOM 和 真实DOM同步起来,这个过程中叫做协调(Reconciliation);
这种编程的方式赋予了React声明式的API:你只需要告诉React希望让UI是什么状态,React来确保DOM和这些状态是匹配的。
你不需要直接进行DOM操作,只可以从手动更改DOM、属性操作、事件处理中解放出来;