Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 169 additions & 0 deletions docs/docs/02.1-jsx-in-depth.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
---
id: jsx-in-depth-zh-CN
title: 深入JSX
permalink: jsx-in-depth-zh-CN.html
prev: displaying-data-zh-CN.html
next: jsx-gotchas-zh-CN.html
---

JSX 是 React 推荐使用的一种 JavaScript XML 语法变种。

>提示:
>
> 不要忘记文件开头的 `/** @jsx React.DOM */`编译指令!它告诉 JSX 为 React 处理这个文件。
>
> 如果你不包含这个编译指令,你的源文件将不被处理,所以如果你想对代码库里所有 JS 文件执行 JSX 转译是安全的。

## 为什么要用 JSX?

React 可以不通过 JSX 直接使用。只需要把你的代码用 `React.DOM` 构造一下。比如,可以这样来构造一个简单的超链接:

```javascript
var link = React.DOM.a({href: 'http://facebook.github.io/react'}, 'React');
```

我们推荐使用 JSX 有很多原因:

* 它能更好地展现 DOM 结构。
* 方便设计师修改。
* 使用过 MXML 和 XAML 的用户会对它很熟悉。

## 转译(The Transform)

JSX 把类 XML 的语法转成原生 JavaScript,XML 元素和属性被相应地转译成方法调用和对象。

```javascript
var Nav;
// 输入 (JSX):
var app = <Nav color="blue" />;
// 输出 (JS):
var app = Nav({color:"blue"});
```

注意为了使用 `<Nav />`,`Nav` 一定要在作用区间里。

JSX 也支持使用 XML 语法定义子结点:

```javascript
var Nav, Profile;
// 输入 (JSX):
var app = <Nav color="blue"><Profile>click</Profile></Nav>;
// 输出 (JS):
var app = Nav({color:"blue"}, Profile(null, "click"));
```

使用 [JSX 编译器](/react/jsx-compiler.html) 来试用 JSX 并理解它是如何编译到原生 JavaScript,还有[HTML 到 JSX 转换器](/react/html-jsx.html) 来把现有 HTML 转成 JSX。

如果你需要使用 JSX,这篇 [入门教程](/react/docs/getting-started.html) 教程来教你怎么搭建编译环境。

> 提示:
>
> 这里给出代码转译细节是为了方便理解,你的代码不应该依赖这些实现细节。

## React 和 JSX

React 和 JSX 是独立的技术,但是 JSX 在设计初时就主要考虑到了 React。两种有效使用 JSX 的场景:

* 构造 React DOM 模块实例 (`React.DOM.*`)。
* 构造复合模块实例,通过 `React.createClass()` 创建。

### React DOM 模块

构造一个 `<div>` 的过程就是创建一个指向 `React.DOM.div` 的变量。

```javascript
var div = React.DOM.div;
var app = <div className="appClass">Hello, React!</div>;
```

### React 复合模块

构造一个复合模块实例,就是创建一个指向这个 class 的变量。

```javascript
var MyComponent = React.createClass({/*...*/});
var app = <MyComponent someProperty={true} />;
```

JSX 通过变量赋值来推断模块名字,并以此给 class 设置相应的 [displayName](/react/docs/component-specs.html#displayName)。

查看 [多重模块](/react/docs/multiple-components.html) 来了解更多复合模块的用法。

> 提示:
>
> 由于 JSX 就是 JavaScript,一些标识符像 `class` 和 `for` 不建议作为 XML
> 属性名。作为替代,React DOM 使用 `className` 和 `htmlFor` 来做对应的属性。

## DOM 便利

为每个类型的 DOM 元素都定义一个变量是非常乏味的(如 `var div, span, h1, h2, ...`)。
JSX 提供一个便利来解决这个问题,通过让你在文件头指定 `@jsx`指令。JSX 会通过它来查找 DOM 模块。

```javascript
/**
* @jsx React.DOM
*/
var Nav;
// 输入 (JSX):
var tree = <Nav><span /></Nav>;
// 输出 (JS):
var tree = Nav(null, React.DOM.span(null));
```

> 提醒:
>
> JSX 只是单纯的把 elements 转换成 function 调用,并没有 DOM 的概念。`@jsx` 指令
> 只是为了便于找到最常用的元素。总之,JSX 没有 DOM 的概念。

## JavaScript 表达式

### 属性表达式

要使用 JavaScript 表达式作为属性值,把这个表达式用一对大括号 (`{}`) 包起来,不要用引号 (`""`)。

```javascript
// 输入 (JSX):
var person = <Person name={window.isLoggedIn ? window.name : ''} />;
// 输出 (JS):
var person = Person({name: window.isLoggedIn ? window.name : ''});
```

### 子节点表达式

同样地,JavaScript 表达式也可用于描述子结点:

```javascript
// 输入 (JSX):
var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
// 输出 (JS):
var content = Container(null, window.isLoggedIn ? Nav(null) : Login(null));
```

### 注释

JSX 里添加注释很容易;它们只是 JS 表达式而已。你只需要在一个标签的子节点内(非最外层)小心地把 `{}` 包围要注释的部分。

```javascript
var content = (
<Nav>
{/* 一般注释, 用 {} 包围 */}
<Person
/* 多
注释 */
name={window.isLoggedIn ? window.name : ''} // 行尾注释
/>
</Nav>
);
```

## 前期工作

JSX 与其它 JavaScript 嵌入 XML 语言的方案/项目
类似。一些让 JSX 与众不同的特性有:

* JSX 只做简单的语法转换。
* JSX 不提供也不需要一个运行时库。
* JSX 不更改也不添加 JavaScript 语义。

JSX 类似于 HTML,但又不完全一样。参照 [JSX 陷阱](/react/docs/jsx-gotchas.html) 了解主要不同。