# 前置知识:JSX
TIP
JSX的本质:不是模板引擎,而是语法糖
设想如下变量声明:
const element = <h1>Hello, world!</h1>;
这个有趣的标签语法既不是字符串也不是 HTML。它被称为 JSX,是一个 JavaScript 的语法扩展。
现在有点意思了,居然能让一个 JS 变量直接赋值成一段“HTML”,让我想起了 Vue 中单文件组件的<template>
# 为什么使用 JSX
React 并没有采用将标记与逻辑分离到不同文件这种人为的分离方式,而是通过将二者共同存放在称之为“组件”的松散耦合单元之中,来实现关注点分离。
# 嵌入表达式
在下面的例子中,我们声明了一个名为 name 的变量,然后在 JSX 中使用它,并将它包裹在大括号中:
const name = "Josh Perez";
const element = <h1>Hello, {name}</h1>;
ReactDOM.render(element, document.getElementById("root"));
在下面的示例中,我们将调用 JavaScript 函数 formatName(user)
的结果,并将结果嵌入到 <h1>
元素中。
function formatName(user) {
return user.firstName + " " + user.lastName;
}
const user = {
firstName: "Harper",
lastName: "Perez"
};
const element = <h1>Hello, {formatName(user)}!</h1>;
ReactDOM.render(element, document.getElementById("root"));
# JSX 也是一个表达式
在编译之后,JSX 表达式会被转为普通 JavaScript 函数调用,并且对其取值后得到 JavaScript 对象。
function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>;
}
return <h1>Hello, Stranger.</h1>;
}
# 指定属性
你可以通过使用引号,来将属性值指定为字符串字面量,也可以使用大括号,来在属性值中插入一个 JavaScript 表达式:
const element1 = <div tabIndex="0"></div>;
const element2 = <img src={user.avatarUrl}></img>;
警告
因为 JSX 语法上更接近 JavaScript 而不是 HTML,所以 React DOM 使用 camelCase(小驼峰命名)来定义属性的名称,而不使用 HTML 属性名称的命名约定。 例如,JSX 里的 class 变成了 className,而 tabindex 则变为 tabIndex。
# 子元素
就像正常编写 HTML 一样,不用管在 JS 中会不支持,Babel 会将这段 JSX 转换成普通的 JS 对象。
const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);
# 默认转义
React DOM 在渲染所有输入内容之前,默认会进行转义。它可以确保在你的应用中,永远不会注入那些并非自己明确编写的内容。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(cross-site-scripting, 跨站脚本)攻击。
const title = response.potentiallyMaliciousInput;
// 直接使用是安全的:
const element = <h1>{title}</h1>;
# JSX 的等价表示
Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用,最终返回一个普通的 JS 对象
- 编写 jsx
- babel 转化 jsx 为渲染函数的 params
- 生成 virtual node 或者说 ReactElement
const element = <h1 className="greeting">Hello, world!</h1>;
const element = React.createElement("h1", { className: "greeting" }, "Hello, world!");
// 注意:这是简化过的结构
const element = {
type: "h1",
props: {
className: "greeting",
children: "Hello, world!"
}
};