# 前置知识: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 对象

  1. 编写 jsx
  2. babel 转化 jsx 为渲染函数的 params
  3. 生成 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!"
  }
};