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的变量、表达式、条件语句、循环语句、函数等。