简析JSX语法

JSX,是一个 JavaScript 的语法扩展。是React组件编写UI逻辑的语言扩展(JSX除了能在React中使用之外还可以用于别的地方)。JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。JSX 可能会使人联想到模版语言,但它具有 JavaScript 的全部功能。

JSX 有以下优点:

  • JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化。
  • 它是类型安全的,在编译过程中就能发现错误。
  • 使用 JSX 编写模板更加简单快速。

JSX 原理

JSX 能在HTML中正常显示必须转换成 DOM,了解更多关于 DOM 的知识请移步DOM 概述,
DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。DOM 是web页面的完全的面向对象表述,即每个DOM元素的结构都可以用JavaScript的对象来表示。

下面这个最简单的DOM元素为例,怎么使用JavaScript的对象来表现一个DOM元素的结果:

1
<h1 class="title">Hello World!</h1>

你会发现,DOM元素包含的信息其实只有三个:标签名(HTML元素)、属性(HTML元素属性)和子元素(HTML元素或文本节点)。那么上面的这个HTML标签对应的所有信息可以用下面这个对象来描述:

1
2
3
4
5
6
7
{
tag: 'div',
attrs: {
className: 'title'
},
children: 'Hello World!'
}

HTML的信息和JavaScript所包含的结构和信息其实是一样的,我们可以用JavaScript对象来描述所有能用HTML表示的UI信息。

在React中会把类似HTML的JSX结构转换成JavaScript的对象结构,如:

1
const element = <h1 className="title">Hello World!</h1>

JSX 实际是一个对象,element包含以下信息:

1
2
3
4
5
6
7
{
type: "h1",
props: {
children: "Hello World!",
className: "title"
}
}

Babel会把JSX转译成一个名为React.createElement()函数调用。比如下面的两段代码,起到的作用是同等的:

1
2
3
4
5
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);

1
2
3
4
5
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);

实际上,JSX 仅仅只是React.createElement(component, props, …children)函数的语法糖。

使用大括号嵌入 JavaScript 表达式

在 JSX 语法中,你可以在大括号内放置任何有效的 JavaScript 表达式:

1
2
const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;

嵌入函数:

1
2
const getName = () => 'Josh Perez';
const element = <h1>Hello, {getName()}</h1>;

注意:if 语句以及 for 循环不是 JavaScript 表达式,所以不能在 JSX 中直接使用。但是,你可以用在 JSX 以外的代码中。

JSX 也是一个表达式

在编译之后,JSX 表达式会被转为普通 JavaScript 函数调用,并且对其取值后得到 JavaScript 对象。

也就是说,你可以在 if 语句和 for 循环的代码块中使用 JSX,将 JSX 赋值给变量,把 JSX 当作参数传入,以及从函数中返回 JSX:

1
2
3
4
5
6
7
8
9
10
const getName = () => 'jofun'

function getGreeting (name) {
if (name) {
return <h1>Hello, {name}</h1>
}
return <h1>Hello, {getName()}</h1>
}

const element = <div>{getGreeting('joe')}</div>

JSX 特定属性

你可以通过使用引号,来将属性值指定为字符串字面量:

1
const element = <div tabIndex="0"></div>

使用大括号,来在属性值中插入一个 JavaScript 表达式:

1
const element = <img src={user.avatarUrl} />

在属性中嵌入 JavaScript 表达式时,不要在大括号外面加上引号。你应该仅使用引号(对于字符串值)或大括号(对于表达式)中的一个,对于同一属性不能同时使用这两种符号。

注意:因为 JSX 语法上更接近 JavaScript 而不是 HTML,所以 React DOM 使用 camelCase(小驼峰命名)来定义属性的名称,而不使用 HTML 属性名称的命名约定。如:tabindex 变为 tabIndex。需要特别注意的是,在JSX中要是会用到class和for属性时,需要将class换成 className,for换成 htmlFor。那是因为class和for是JavaScript中的关键字。

使用 JSX 指定子元素

JSX 标签里和HTML一样能够嵌套包含子元素:

1
2
3
4
5
6
const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);

JSX 防止注入攻击

你可以安全地在 JSX 当中插入用户输入内容:

1
2
3
const title = response.potentiallyMaliciousInput;
// 直接使用是安全的:
const element = <h1>{title}</h1>;

React DOM 在渲染所有输入内容之前,默认会进行转义。它可以确保在你的应用中,永远不会注入那些并非自己明确编写的内容。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(cross-site-scripting, 跨站脚本)攻击。