diff --git a/docs/docs/01-why-react.zh-CN.md b/docs/docs/01-why-react.zh-CN.md index 2fda6327937..98e8abd3c66 100644 --- a/docs/docs/01-why-react.zh-CN.md +++ b/docs/docs/01-why-react.zh-CN.md @@ -13,9 +13,9 @@ React 是一个 Facebook 和 Instagram 用来创建用户界面的 JavaScript 仅仅只要表达出你的应用程序在任一个时间点应该长的样子,然后当底层的数据变了,React 会自动处理所有用户界面的更新。 -### 表达能力 (Declarative) +### 声明式 (Declarative) -当数据变化了,React 概念上是类似点击了更新的按钮,但仅会更新变化的部分。 +数据变化后,React 概念上与点击“刷新”按钮类似,但仅会更新变化的部分。 ## 构建可组合的组件 diff --git a/docs/docs/02-displaying-data.zh-CN.md b/docs/docs/02-displaying-data.zh-CN.md index d964bfac8a2..9e9f5d2d4ea 100644 --- a/docs/docs/02-displaying-data.zh-CN.md +++ b/docs/docs/02-displaying-data.zh-CN.md @@ -7,7 +7,8 @@ prev: why-react-zh-CN.html next: jsx-in-depth.html --- -通过用户界面,最基础可以做的事就是显示一些数据。React 让显示数据变得简单,当数据变化的时候,用户界面会自动同步更新。 +用户界面能做的最基础的事就是显示一些数据。React 让显示数据变得简单,当数据变化的时候,用户界面会自动同步更新。 + ## 开始 @@ -54,6 +55,7 @@ setInterval(function() { }, 500); ``` + ## 被动更新 (Reactive Updates) 在浏览器中打开 `hello-react.html` ,在输入框输入你的名字。你会发现 React 在用户界面中只改变了时间, 任何你在输入框输入的内容一直保留着,即使你没有写任何代码来完成这个功能。React 为你解决了这个问题,做了正确的事。 @@ -62,6 +64,7 @@ setInterval(function() { 对这个组件的输入称为 `props` - "properties"的缩写。得益于 JSX 语法,它们通过参数传递。你必须知道在组件里,这些属性是不可改变的,也就是说 **`this.props` 是只读的**。 + ## 组件就像是函数 React 组件非常简单。你可以认为它们就是简单的函数,接受 `props` 和 `state` (后面会讨论) 作为参数,然后渲染出 HTML。正是应为它们是这么的简单,这使得它们非常容易理解。 @@ -70,6 +73,7 @@ React 组件非常简单。你可以认为它们就是简单的函数,接受 ` > > **只有一个限制**: React 组件只能渲染单个根节点。如果你想要返回多个节点,它们*必须*被包含在同一个节点里。 + ## JSX 语法 我们坚信组件是正确方法去做关注分离,而不是通过“模板”和“展示逻辑”。我们认为标签和生成它的代码是紧密相连的。此外,展示逻辑通常是很复杂的,通过模板语言实现这些逻辑会产生大量代码。 @@ -80,6 +84,34 @@ React 组件非常简单。你可以认为它们就是简单的函数,接受 ` JSX 非常小;上面“hello, world”的例子使用了 JSX 所有的特性。想要了解更多,请看 [深入理解 JSX](/react/docs/jsx-in-depth.html)。或者直接使用[在线 JSX 编译器](/react/jsx-compiler.html)观察变化过程。 -JSX 类似于 HTML,但不是完全一样。参考[JSX gotchas](/react/docs/jsx-gotchas.html) 学习关键区别。 +JSX 类似于 HTML,但不是完全一样。参考 [JSX 陷阱](/react/docs/jsx-gotchas.html) 学习关键区别。 最简单开始学习 JSX 的方法就是使用浏览器端的 `JSXTransformer`。我们强烈建议你不要在生产环境中使用它。你可以通过我们的命令行工具 [react-tools](http://npmjs.org/package/react-tools) 包来预编译你的代码。 + + +## 没有 JSX 的 React + +你完全可以选择是否使用 JSX,并不是 React 必须的。你可以通过 `React.createElement` 来创建一个树。第一个参数是标签,第二个参数是一个属性对象,每三个是子节点。 + +```javascript +var child = React.createElement('li', null, 'Text Content'); +var root = React.createElement('ul', { className: 'my-list' }, child); +React.render(root, document.body); +``` + +方便起见,你可以创建基于自定义组件的速记工厂方法。 + +```javascript +var Factory = React.createFactory(ComponentClass); +... +var root = Factory({ custom: 'prop' }); +React.render(root, document.body); +``` + +React 已经为 HTML 标签提供内置工厂方法。 + +```javascript +var root = React.DOM.ul({ className: 'my-list' }, + React.DOM.li(null, 'Text Content') + ); +``` diff --git a/docs/docs/02.1-jsx-in-depth.zh-CN.md b/docs/docs/02.1-jsx-in-depth.zh-CN.md index 0c7b30c131e..c8cf7b16c30 100644 --- a/docs/docs/02.1-jsx-in-depth.zh-CN.md +++ b/docs/docs/02.1-jsx-in-depth.zh-CN.md @@ -8,6 +8,7 @@ next: jsx-spread-zh-CN.html [JSX](http://facebook.github.io/jsx/) 是一个看起来很像 XML 的 JavaScript 语法扩展。React 可以用来做简单的 JSX 句法转换。 + ## 为什么要用 JSX? 你不需要为了 React 使用 JSX,可以直接使用原生 JS。但是,我们建议使用 JSX 是因为它能精确,也是常用的定义包含属性的树状结构的语法。 @@ -18,9 +19,10 @@ XML 有固定的标签开启和闭合的优点。这能让复杂的树更易于 它没有修改 JavaScript 语义。 -## HTML 标签 对比 React 模块 -React 可以渲染 HTML 标签 (strings) 或 React 模块 (classes)。 +## HTML 标签对比 React 组件 + +React 可以渲染 HTML 标签 (strings) 或 React 组件 (classes)。 要渲染 HTML 标签,只需在 JSX 里使用小写字母开头的标签名。 @@ -29,7 +31,7 @@ var myDivElement =
; React.render(myDivElement, document.body); ``` -要渲染 React 模块,只需创建一个大写字母开头的本地变量。 +要渲染 React 组件,只需创建一个大写字母开头的本地变量。 ```javascript var MyComponent = React.createClass({/*...*/}); @@ -37,13 +39,14 @@ var myElement = ; React.render(myElement, document.body); ``` -React 的 JSX 里约定分别使用首字母大、小写来区分本地模块的类和 HTML 标签。 +React 的 JSX 里约定分别使用首字母大、小写来区分本地组件的类和 HTML 标签。 > 提示: > > 由于 JSX 就是 JavaScript,一些标识符像 `class` 和 `for` 不建议作为 XML > 属性名。作为替代,React DOM 使用 `className` 和 `htmlFor` 来做对应的属性。 + ## 转换(Transform) JSX 把类 XML 的语法转成原生 JavaScript,XML 元素、属性和子节点被转换成 `React.createElement` 的参数。 @@ -82,6 +85,7 @@ var app = React.createElement( > 的模式是把 ReactElement 当作一个行内的对象字面量形式来绕过 > `React.createElement` 里的校验代码。 + ## JavaScript 表达式 ### 属性表达式 @@ -133,4 +137,4 @@ var content = ( > 提示: > -> JSX 类似于 HTML,但不完全一样。参考 [JSX 陷阱](/react/docs/jsx-gotchas.html) 了解主要不同。 \ No newline at end of file +> JSX 类似于 HTML,但不完全一样。参考 [JSX 陷阱](/react/docs/jsx-gotchas.html) 了解主要不同。 diff --git a/docs/docs/02.2-jsx-spread.zh-CN.md b/docs/docs/02.2-jsx-spread.zh-CN.md index b1fd4741c14..d35be74cb5b 100644 --- a/docs/docs/02.2-jsx-spread.zh-CN.md +++ b/docs/docs/02.2-jsx-spread.zh-CN.md @@ -1,17 +1,18 @@ --- id: jsx-spread-zh-CN -title: JSX 展开属性 (Spread Attributes) +title: JSX 展开属性 permalink: jsx-spread-zh-CN.html prev: jsx-in-depth-zh-CN.html next: jsx-gotchas-zh-CN.html --- -如果你事先知道模块需要的全部 Props(属性),JSX 很容易地这样写: +如果你事先知道组件需要的全部 Props(属性),JSX 很容易地这样写: ```javascript var component = ; ``` + ## 修改 Props 是不好的,明白吗 如果你不知道要设置哪些 Props,那么现在最好不要设置它: @@ -26,9 +27,10 @@ next: jsx-gotchas-zh-CN.html Props 应该被当作禁止修改的。修改 props 对象可能会导致预料之外的结果,所以最好不要去修改 props 对象。 -## 扩展属性 (Spread Attributes) -现在你可以使用 JSX 的新特性 - 扩展属性: +## 展开属性(Spread Attributes) + +现在你可以使用 JSX 的新特性 - 展开属性: ```javascript var props = {}; @@ -37,7 +39,7 @@ Props 应该被当作禁止修改的。修改 props 对象可能会导致预料 var component = ; ``` -传入对象的属性会被复制到模块内。 +传入对象的属性会被复制到组件内。 它能被多次使用,也可以和其它属性一起用。注意顺序很重要,后面的会覆盖掉前面的。 @@ -47,6 +49,7 @@ Props 应该被当作禁止修改的。修改 props 对象可能会导致预料 console.log(component.props.foo); // 'override' ``` + ## 这个奇怪的 `...` 标记是什么? -这个 `...` 操作符(也被叫做)已经被 [ES6 数组](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) 支持。相关的还有 ES7 规范草案中的 [Object 剩余和展开属性(Rest and Spread Properties)](https://github.com/sebmarkbage/ecmascript-rest-spread)。我们利用了这些还在制定中标准中已经被支持的特性来使 JSX 拥有更优雅的语法。 \ No newline at end of file +这个 `...` 操作符(也被叫做)已经被 [ES6 数组](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) 支持。相关的还有 ES7 规范草案中的 [Object 剩余和展开属性(Rest and Spread Properties)](https://github.com/sebmarkbage/ecmascript-rest-spread)。我们利用了这些还在制定中标准中已经被支持的特性来使 JSX 拥有更优雅的语法。 diff --git a/docs/docs/02.3-jsx-gotchas.zh-CN.md b/docs/docs/02.3-jsx-gotchas.zh-CN.md new file mode 100644 index 00000000000..ad68fd3693a --- /dev/null +++ b/docs/docs/02.3-jsx-gotchas.zh-CN.md @@ -0,0 +1,67 @@ +--- +id: jsx-gotchas-zh-CN +title: JSX 陷阱 +permalink: jsx-gotchas-zh-CN.html +prev: jsx-spread-zh-CN.html +next: interactivity-and-dynamic-uis-zh-CN.html +--- + +JSX 与 HTML 非常相似,但是有些关键区别要注意。 + +> 提示: +> +> 关于 DOM 的区别,如行内样式属性 `style`,参考 [DOM 区别](/react/docs/dom-differences.html) + +## HTML 实体 + +HTML 实体可以插入到 JSX 的文本中。 + +```javascript +
First · Second
+``` + +如果想在 JSX 表达式中显示 HTML 实体,可以会遇到二次转义的问题,因为 React 默认会转义所有字符串,为了防止各种 XSS 攻击。 + +```javascript +// 错误: 会显示 “First · Second” +
{'First · Second'}
+``` + +有多种绕过的方法。最简单的是直接用 Unicode 字符。这时要确保文件是 UTF-8 编码且网页也指定为 UTF-8 编码。 + +```javascript +
{'First · Second'}
+``` + +安全的做法是先找到 [实体的 Unicode 编号](http://www.fileformat.info/info/unicode/char/b7/index.htm) ,然后在 JavaScript 字符串里使用。 + +```javascript +
{'First \u00b7 Second'}
+
{'First ' + String.fromCharCode(183) + ' Second'}
+``` + +可以在数组里混合使用字符串和 JSX 元素。 + +```javascript +
{['First ', ·, ' Second']}
+``` + +万不得已,可以直接使用原始 HTML。 + +```javascript +
+``` + +## 自定义 HTML 属性 + +如果往原生 HTML 元素里传入 HTML 规范里不存在的属性,React 不会显示它们。如果需要使用自定义属性,要加 `data-` 前缀。 + +```javascript +
+``` + +以 `aria-` 开头的 [网络无障碍] 属性可以正常使用。 + +```javascript +
+``` diff --git a/docs/docs/03-interactivity-and-dynamic-uis.zh-CN.md b/docs/docs/03-interactivity-and-dynamic-uis.zh-CN.md new file mode 100644 index 00000000000..4ffb15e2db9 --- /dev/null +++ b/docs/docs/03-interactivity-and-dynamic-uis.zh-CN.md @@ -0,0 +1,86 @@ +--- +id: interactivity-and-dynamic-uis-zh-CN +title: 动态交互式用户界面 +permalink: interactivity-and-dynamic-uis-zh-CN.html +prev: jsx-gotchas-zh-CN.html +next: multiple-components-zh-CN.html +--- + +我们已经学习如何使用 React [显示数据](/react/docs/displaying-data.html)。现在让我们来学习如何创建交互式界面。 + + +## 简单例子 + +```javascript +var LikeButton = React.createClass({ + getInitialState: function() { + return {liked: false}; + }, + handleClick: function(event) { + this.setState({liked: !this.state.liked}); + }, + render: function() { + var text = this.state.liked ? 'like' : 'haven\'t liked'; + return ( +

+ You {text} this. Click to toggle. +

+ ); + } +}); + +React.render( + , + document.getElementById('example') +); +``` + + +## 事件处理与合成事件(Synthetic Events) + +React 里只需把事件处理器(event handler)以骆峰命名(camelCased)形式当作组件的 props 传入即可,就像使用普通 HTML 那样。React 内部创建一套合成事件系统来使所有事件在 IE8 和以上浏览器表现一致。也就是说,React 知道如何冒泡和捕获事件,而且你的事件处理器接收到的 events 参数与 [W3C 规范](http://www.w3.org/TR/DOM-Level-3-Events/) 一致,无论你使用哪种浏览器。 + +如果需要在手机或平板等触摸设备上使用 React,需要调用 `React.initializeTouchEvents(true);` 启用触摸事件处理。 + +## 幕后原理:自动绑定(Autobinding)和事件代理(Event Delegation) + +在幕后,React 做了一些操作来让代码高效运行且易于理解。 + +**Autobinding:** 在 JavaScript 里创建回调的时候,为了保证 `this` 的正确性,一般都需要显式地绑定方法到它的实例上。有了 React,所有方法被自动绑定到了它的组件实例上。React 还缓存这些绑定方法,所以 CPU 和内存都是非常高效。而且还能减少打字! + +**事件代理 :** React 实际并没有把事件处理器绑定到节点本身。当 React 启动的时候,它在最外层使用唯一一个事件监听器处理所有事件。当组件被加载和卸载时,只是在内部映射里添加或删除事件处理器。当事件触发,React 根据映射来决定如何分发。当映射里处理器时,会当作空操作处理。参考 [David Walsh 很棒的文章](http://davidwalsh.name/event-delegate) 了解这样做高效的原因。 + + +## 组件其实是状态机(State Machines) + +React 把用户界面当作简单状态机。把用户界面想像成拥有不同状态然后渲染这些状态,可以轻松让用户界面和数据保持一致。 + +React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。React 来决定如何最高效地更新 DOM。 + + +## State 工作原理 + +常用的通知 React 数据变化的方法是调用 `setState(data, callback)`。这个方法会合并(merge) `data` 到 `this.state`,并重新渲染组件。渲染完成后,调用可选的 `callback` 回调。大部分情况下不需要提供 `callback`,因为 React 会负责把界面更新到最新状态。 + + +## 哪些组件应该有 State? + +大部分组件的工作应该是从 `props` 里取数据并渲染出来。但是,有时需要对用户输入、服务器请求或者时间变化等作出响应,这时才需要使用 State。 + +** 尝试把尽可能多的组件无状态化。** 这样做能隔离 state,把它放到最合理的地方,也能减少冗余并,同时易于解释程序运作过程。 + +常用的模式是创建多个只负责渲染数据的无状态(stateless)组件,在它们的上层创建一个有状态(stateful)组件并把它的状态通过 `props` 传给子级。这个有状态的组件封装了所有用户的交互逻辑,而这些无状态组件则负责声明式地渲染数据。 + + +## 哪些 *应该* 作为 State? + +**State 应该包括那些可能被组件的事件处理器改变并触发用户界面更新的数据。** 真实的应用中这种数据一般都很小且能被 JSON 序列化。当创建一个状态化的组件时,想象一下表示它的状态最少需要哪些数据,并只把这些数据存入 `this.state`。在 `render()` 里再根据 state 来计算你需要的其它数据。你会发现以这种方式思考和开发程序最终往往是正确的,因为如果在 state 里添加冗余数据或计算所得数据,需要你经常手动保持数据同步,不能让 React 来帮你处理。 + + +## 哪些 *不应该* 作为 State? + +`this.state` 应该仅包括能表示用户界面状态所需的最少数据。因些,它不应该包括: + +* **计算所得数据:** 不要担心根据 state 来预先计算数据 —— 把所有的计算都放到 `render()` 里更容易保证用户界面和数据的一致性。例如,在 state 里有一个数组(listItems),我们要把数组长度渲染成字符串, 直接在 `render()` 里使用 `this.state.listItems.length + ' list items'` 比把它放到 state 里好的多。 +* **React 组件:** 在 `render()` 里使用当前 props 和 state 来创建它。 +* **基于 props 的重复数据:** 尽可能使用 props 来作为惟一数据来源。把 props 保存到 state 的一个有效的场景是需要知道它以前值的时候,因为未来的 props 可能会变化。 diff --git a/docs/docs/getting-started.zh-CN.md b/docs/docs/getting-started.zh-CN.md index a489caff888..79a2ccdcdac 100644 --- a/docs/docs/getting-started.zh-CN.md +++ b/docs/docs/getting-started.zh-CN.md @@ -1,19 +1,20 @@ --- id: getting-started-zh-CN title: 入门教程 -next: tutorial.html +next: tutorial-zh-CN.html +redirect_from: "docs/index-zh-CN.html" --- ## JSFiddle -开始 Hack React 的最简单的方法是用下面 JSFiddle 的Hello Worlds +开始 Hack React 的最简单的方法是用下面 JSFiddle 的Hello Worlds: * **[React JSFiddle](http://jsfiddle.net/reactjs/69z2wepo/)** * [React JSFiddle without JSX](http://jsfiddle.net/reactjs/5vjqabv3/) ## 入门教程包 (Starter Kit) -开始先下载入门教程包 +开始先下载入门教程包。 -在入门教程包的根目录,创建一个含有下面代码的 `helloworld.html` +在入门教程包的根目录,创建一个含有下面代码的 `helloworld.html`。 ```html @@ -93,7 +94,7 @@ React.render( Hello React! - +
@@ -102,11 +103,16 @@ React.render( ``` + ## 想用 CommonJS? -如果你想在一个模块系统里使用 React,[fork 我们的代码](http://github.com/facebook/react), `npm install` 然后运行 `grunt`。一个漂亮的 CommonJS 模块集将会被生成。我们的 `jsx` 转换工具可以很轻松的集成到大部分打包系统里(不仅仅是 CommonJS)。 +如果你想在 [browserify](http://browserify.org/),[webpack](http://webpack.github.io/) 或者或其它兼容CommonJS的模块系统里使用 React,只要使用 [`react` npm 包](https://www.npmjs.org/package/react) 即可。而且,`jsx` 转换工具可以很轻松的地集成到大部分打包系统里(不仅仅是 CommonJS)。 + ## 下一步 -去看看[入门教程](/react/docs/tutorial.html),然后学习其他在 `/examples` 目录里的示例代码。祝你好运,欢迎来到 React 的世界。 +去看看[入门教程](/react/docs/tutorial.html) 和入门教程包 `examples` 目录下的其它例子学习更多。 + +我们还有一个社区开发者共建的 Wiki:[workflows, UI-components, routing, data management etc.](https://github.com/facebook/react/wiki/Complementary-Tools) +恭喜你,欢迎来到 React 的世界。