JSX 是 React 中用来描述 UI 的语法扩展,看起来像 HTML,但它不是 HTML,也不是模板字符串,而是 JavaScript 的语法糖。浏览器不能直接识别 JSX,需要 Babel、TypeScript、SWC 等工具编译。
1. 基本样子
const name = "Alice";
const element = (
<h1 className="title">
Hello, {name}
</h1>
);
其中:
className对应 HTML 的class{}里可以写 JavaScript 表达式- JSX 本身是一个表达式,可以赋值、传参、返回
2. 编译后是什么
传统 JSX transform 会把它编译成:
const element = React.createElement(
"h1",
{ className: "title" },
"Hello, ",
name
);
React 17 之后的新 JSX transform 会自动引入运行时:
import { jsx as _jsx } from "react/jsx-runtime";
const element = _jsx("h1", {
className: "title",
children: ["Hello, ", name]
});
所以现代 React 项目里,很多时候不写 import React 也能用 JSX。
3. 本质
JSX 的本质是
React.createElement/jsx调用的语法糖,用来创建 React Element。
它编译后返回的不是 DOM 节点,也不是组件实例,而是一个普通的 JavaScript 对象,大概长这样:
{
type: "h1",
props: {
className: "title",
children: ["Hello, ", name]
},
key: null,
ref: null,
$$typeof: Symbol(react.element)
}
这个对象叫 React Element,它只是对 UI 的描述。React 后续会根据这棵 Element 树进行协调,最终生成或更新真实 DOM。
4. 几个关键点
<div />编译后type是字符串"div"<MyComponent />编译后type是函数或类组件本身<></>是React.Fragment的语法糖{}里只能放表达式,不能直接放if、for语句- 属性通常是 camelCase,如
onClick、className style接收对象:style={{ color: "red" }}key是 React 的特殊属性,用于列表协调
5. JSX总结
JSX 不是 HTML,也不是模板引擎。
它是 JavaScript 的语法扩展,编译后变成创建 React Element 的函数调用。
React Element 是描述 UI 的普通对象,React 再根据它进行协调和渲染。
所以 JSX 的本质就是:声明式 UI 语法 + React Element 工厂调用的语法糖。
出现<>, 会自动创建元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<div id="example"></div>
<!-- React 16.14.0 核心库 -->
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<!-- ReactDOM 16.14.0 -->
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<!-- Babel转换器 (替代browser.min.js) -->
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
//在JSX中, 出现<>, 会自动创建元素
ReactDOM.render(
<h1>Hello React!</h1>,
document.getElementById("example")
);
</script>
</body>
</html>
出现{}, 认为是变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<div id="example"></div>
<!-- React 16.14.0 核心库 -->
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<!-- ReactDOM 16.14.0 -->
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<!-- Babel转换器 (替代browser.min.js) -->
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
//在JSX中, 出现{}, 认为是变量
var text = "学姐";
ReactDOM.render(
<h1>哈喽, {text}!</h1>,
document.getElementById("example")
);
</script>
</body>
</html>
如何写html标签属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
<style type="text/css">
.bg {
background: yellow;
}
</style>
</head>
<body>
<div id="example"></div>
<!-- React 16.14.0 核心库 -->
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<!-- ReactDOM 16.14.0 -->
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<!-- Babel转换器 (替代browser.min.js) -->
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
//1.在渲染的元素内容中, 不能出现for, class, 因为和React中的关键词重名
//for 写成 htmlFor
//class 写成 className
//2.渲染的元素内容, 只能有一个根节点
//3.单标签需要用/闭合
ReactDOM.render(
<div className="bg">
<label htmlFor="username">用户名:</label>
<input type="text" id="username" />
</div>,
document.getElementById("example")
);
</script>
</body>
</html>
循环渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<div id="example"></div>
<!-- React 16.14.0 核心库 -->
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<!-- ReactDOM 16.14.0 -->
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<!-- Babel转换器 (替代browser.min.js) -->
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
var arr = ["宝宝", "蓉蓉", "经纪人", "楼上邻居", "隔壁老王"];
ReactDOM.render(
<ul>
<li>{arr[0]}</li>
<li>{arr[1]}</li>
<li>{arr[2]}</li>
<li>{arr[3]}</li>
</ul>,
document.getElementById("example")
);
//循环操作
ReactDOM.render(
<ul>
{arr.map(function (e) {
return <li>Hi, {e}!</li>;
})}
</ul>,
document.getElementById("example")
);
</script>
</body>
</html>
写表达式(变量,运算,函数调用)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<div id="example"></div>
<!-- React 16.14.0 核心库 -->
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<!-- ReactDOM 16.14.0 -->
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<!-- Babel转换器 (替代browser.min.js) -->
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
//注: JSX中的{}中, 可以写表达式(变量,运算,函数调用)
ReactDOM.render(
<div>1 + 1 = {1 + 1}</div>,
document.getElementById("example")
);
</script>
</body>
</html>
数组存放html元素可直接渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<div id="example"></div>
<!-- React 16.14.0 核心库 -->
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<!-- ReactDOM 16.14.0 -->
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<!-- Babel转换器 (替代browser.min.js) -->
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
//数组中存放元素
var arr1 = [
<h1>Hello world!</h1>,
<h2>你好, 世界!</h2>,
<h3>莎娃迪卡!</h3>,
];
//当数组中存放的是元素, 可以直接使用数组进行渲染, 相当于把数组的每个元素进行渲染
ReactDOM.render(<div>{arr1}</div>, document.getElementById("example"));
</script>
</body>
</html>