JSX

146 阅读2分钟

JSX 是 JavaScript 的语法扩展,可以在javascript文件里面书写类似于HTML的标签。有点类似于其他的模版语法,比如:java 的 jsp 文件,或者 nodejs 的 ejs 等。比如下面这段简单的JSX:

const element = <h1 className="title">hello,JSX</h1>;

为什么要用JSX呢?

React不强制一定要使用JSX,从React的工作原理来讲的话,React本身是基于虚拟DOM来生成真实的HTML DOM节点的,虚拟DOM其实就是一个JavaScript对象,所以呢,对于React应用,完完全全是可以通过纯纯的JavaScript的方式来编写应用的,不需要写半点HTML或者说JSX。

那为什么要用JSX来写呢?

无非就是为了简单方便,想象一下,如果全部用纯纯的JavaScript来写HTML DOM生成部分,那代码量可以想象肯定是非常非常之多,同时呢,也不够直观表达出DOM的结构。对于WEB开发者来说,对于HTML本身就非常熟悉,这样感觉比较贴合传统的开发模式。保留了同样的方式去设置Attribute、Event、Style等(当然有一些小小的不一样,比如className,onClick等)。

JSX对应的React创建元素方法

对于上面那段简单的JSX,转成React对象的方式去创建的话,如下:

// JSX
const element = <h1>hello,JSX</h1>;
// 等价于
const element = React.createElement(
    'h1',
    {className: 'title'},
    'hello, JSX'
)

所以,如果你喜欢,完全可以不必用JSX,全部使用React.createElement去构建你的React应用,一点问题没有。

JSX最终是被如何转换成JavaScript对象的呢?

在写React组件的时候,如果用到JSX语法,文件名后缀一般为:.jsx, .tsx,否则编辑器会无法识别JSX语法。

这里呢发生了一些事情,不得不提到一个叫做Babel的JavaScript语法解析器。这里以webpack打包工具为例,在项目中会有对应的webpack打包配置,配置里面有对应的loader专门就是配置了.jsx, .tsx文件对应的babel-loader解析模块。比如如下配置:

{
  test: /\.(js|mjs|jsx|ts|tsx)$/,
  loader: require.resolve('babel-loader'),
  options: {
    customize: require.resolve(
      'babel-preset-react-app/webpack-overrides'
    ),
    presets: [
      [
        require.resolve('babel-preset-react-app'),
        {
          runtime: hasJsxRuntime ? 'automatic' : 'classic',
        },
      ],
    ],
  }
}

所以,JSX语法在项目构建编译阶段,其实已经被babel-loader处理转换成了对应的ReactElement, 是等价于 React.createElement 的。

最后

JSX 简单理解就是JavaScript。在JSX中同样可以使用JavaScript的变量、表达式、条件语句、循环语句、函数等。