一个 React 组件

  1. import React, { Component } from 'react';
  2. import ReactDOM from 'react-dom';
  3. class App extends Component {
  4. render() {
  5. return (
  6. <div className="App">
  7. <span>Hello, World.</span>
  8. </div>
  9. );
  10. }
  11. }
  12. ReactDOM.render(<App />, document.getElementById('root'));

这是一个非常简单的 React 组件,App 组件继承了 Component,而它的 render 方法返回了一个“HTML”,这个方法看起来就像一段“HTML”嵌入在 JavaScript 代码内部。很显然,这段代码直接在浏览器环境下是无法运行的,这并不是一段正常的 JavaScript 代码。

它就是 JSX

什么是 JSX

JSX 是一种类似 XML 语法的语法扩展,可以被编译成“合法”的 JavaScript 代码。

那么如何用一段“合法”的 JavaScript 代码来描述这段 JSX 呢?

那么让我们把一个 DOM 抽象成一个 JavaScript 对象,用对象的属性来描述这个 DOM 的结构,比如标签名、属性、子 DOM 等等。

我们尝试用 JavaScript 对象来描述第一个例子中的 JSX

  1. {
  2. tag: 'div',
  3. attrs: {
  4. className: 'App',
  5. },
  6. children: [
  7. {
  8. tag: 'span',
  9. text: 'Hello, World.'
  10. }
  11. ]
  12. }

那么我们第一个例子中的代码,在编译后就会变成这样一段“合法”的 JavaScript 代码。

  1. import React, { Component } from 'react';
  2. import ReactDOM from 'react-dom';
  3. class App extends Component {
  4. render() {
  5. return (
  6. React.createElement(
  7. 'div',
  8. { className: 'App' },
  9. React.createElement(
  10. 'span',
  11. null,
  12. 'Hello, World.'
  13. )
  14. )
  15. );
  16. }
  17. }
  18. ReactDOM.render(React.createElement(App), document.getElementById('root'))

createElement 这个函数会将入参进行处理,最终返回一个以 JavaScript 对象为基础的结构描述我们最终想要得到的 DOM 对象。最终,通过 ReactDOM.render 方法,将所得到的 JavaScript 对象转换成真正的 DOM

最后

到此,我们知道了,我们所写的 JSX,其实最终都会被编译成为 JavaScript 对象,正是因为这层的抽象,所以使跨平台成为了可能,对于所有拥有 JavaScript 运行环境的平台,我们都可以执行它。
此外,因为将它抽象成了 JavaScript 对象,所以我们也可以更方便地进行 diff/patch(React中的比对算法,用于比对后更新DOM结构)。而不是当数据产生变化的时候,我们直接去比对处理 DOM,这也很大程度上优化了它的性能。