Browse Source

Merge pull request #4965 from iamchenxin/translate

[docs] Update zh-CN docs.
main
Jim 9 years ago
parent
commit
3380ccdaf4
  1. 0
      docs/08-working-with-the-browser.zh-CN.md
  2. 174
      docs/08.1-more-about-refs.zh-CN.md
  3. 74
      docs/09-tooling-integration.zh-CN.md
  4. 25
      docs/10-addons.zh-CN.md
  5. 252
      docs/10.1-animation.zh-CN.md

0
docs/08-working-with-the-browser-zh-CN.md → docs/08-working-with-the-browser.zh-CN.md

174
docs/08.1-more-about-refs.zh-CN.md

@ -0,0 +1,174 @@
---
id: more-about-refs-zh-CN
title: 关于Refs的更多内容
permalink: more-about-refs-zh-CN.html
prev: working-with-the-browser-zh-CN.html
next: tooling-integration-zh-CN.html
---
从render方法返回你的UI结构以后,你也许发现自己想“接触”并且调用从 `render()`返回的组件实例上的方法。通常,这样做对于让数据流过你的应用并不是必须的,因为Reactive的数据流总是确保最新的`props` 被发送到 `render()`输出的每个子级。然而,有一些情况下它仍旧是必要或者有益的。
考虑这样一种场景,当你想要告诉一个`<input />` 元素(存在于你的实例的子层级)在你更新他的值为空字符串后获得焦点。
```javascript
var App = React.createClass({
getInitialState: function() {
return {userInput: ''};
},
handleChange: function(e) {
this.setState({userInput: e.target.value});
},
clearAndFocusInput: function() {
this.setState({userInput: ''}); // Clear the input
// We wish to focus the <input /> now!
},
render: function() {
return (
<div>
<div onClick={this.clearAndFocusInput}>
Click to Focus and Reset
</div>
<input
value={this.state.userInput}
onChange={this.handleChange}
/>
</div>
);
}
});
```
注意,在这个例子中,我们想 "告诉" input 一些东西 - 那些最后它不能从他的props推断出来的东西。在这个场景中我们想 "告诉" 它,它应该转为获得焦点。然而,有一些挑战。从`render()` 返回的东西不是你实际的 "子" 组件的组合,而是一个在某刻特定实例的子组件的 *描述* - 一个快照。
> 注意:
>
> 记住,从 `render()`返回的东西不是你的 *实际的* 被渲染出的子组件实例。从 `render()` 返回的东西仅仅是一个在特定时间你的组件的子层级中的子实例的 *描述*
这意味着你万万不要把你从`render()`返回的东西 "抓住不放" 然后期望它变成任何有意义的东西。
```javascript
// 反面模式: 这行不通.
render: function() {
var myInput = <input />; // I'm going to try to call methods on this
this.rememberThisInput = myInput; // input at some point in the future! YAY!
return (
<div>
<div>...</div>
{myInput}
</div>
);
}
```
在这个例子中,`<input />` 仅仅是一个`<input />` 的 *描述*。 这个描述被用于为`<input />`创建一个 *真实的* **支持实例(backing instance)**
所以我们如何与input的 *真实的*支持实例对话?
## ref String 属性
React支持一种非常特殊的属性,你可以附加到任何从`render()`输出的组件上。这个特殊的属性允许你引用任何从`render()`返回的东西的对应 **支持实例(backing instance)** 。它总是保证是适当的实例,在任何时点上。
就是这么简单:
1. 赋值`ref`属性为任何从`render` 返回的东西,比如:
```html
<input ref="myInput" />
```
2. 在其他一些代码中(典型的事件处理代码),通过`this.refs`访问 **支持实例(backing instance)**,如:
```javascript
this.refs.myInput
```
你可以直接通过调用`React.findDOMNode(this.refs.myInput)` 访问组件的DOM node。
## ref 回调属性
`ref` 属性可以是一个回调函数而不是名字。这个回调函数将会在组件挂载以后立即执行。被引用的组件将被作为参数传递,并且回调函数可以立即使用组件,或者保存引用将来使用(或两者都是)。
通过使用ES6的箭头函数,它像添加一个`ref`属性到任何从`render`返回的东西一样简单。
```html
render: function() {
return <TextInput ref={(c) => this._input = c} />;
},
componentDidMount: function() {
this._input.focus();
},
```
或者
```html
render: function() {
return (
<TextInput
ref={function(input) {
if (input != null) {
input.focus();
}
}} />
);
},
```
注意当被引用的组件卸载和每当ref变动,旧的ref将会被以`null`做参数调用。这阻止了在实例被保存的情况下的内存泄露,如第一个例子。注意当像在这里的例子,使用内联函数表达式写refs,React在每次更新都看到不同的函数对象,ref将会被以`null` 立即调用在它被以组件实例调用前。
## 完成的示例
```javascript
var App = React.createClass({
getInitialState: function() {
return {userInput: ''};
},
handleChange: function(e) {
this.setState({userInput: e.target.value});
},
clearAndFocusInput: function() {
// Clear the input
this.setState({userInput: ''}, function() {
// This code executes after the component is re-rendered
React.findDOMNode(this.refs.theInput).focus(); // Boom! Focused!
});
},
render: function() {
return (
<div>
<div onClick={this.clearAndFocusInput}>
Click to Focus and Reset
</div>
<input
ref="theInput"
value={this.state.userInput}
onChange={this.handleChange}
/>
</div>
);
}
});
```
在这个例子中, 我们的render函数返回一个 `<input />` 实例的描述。但是真正的实例通过 `this.refs.theInput` 访问。只要带有`ref="theInput"`的子组件从 `render`被返回,`this.refs.theInput` 就可以访问正确的实例。这甚至在更高层(non-DOM)的组件上生效,比如`<Typeahead ref="myTypeahead" />`。
## 总结
Refs是一种很好的发送消息给特定子实例(通过流式的Reactive `props``state`来做会不方便)的方式。它们应该,不论怎样,不是你数据流通你的应用的首选。默认方式,使用Reactive数据流并为本身不是reactive的用例保存`ref`。
### 优点:
- 你可以在你的组件类里定义任何的公开方法(比如在一个Typeahead的重置方法)然后通过refs调用那些公开方法(比如`this.refs.myTypeahead.reset()`)。
- 实行DOM测量几乎总是需要接触到"原生" 组件比如 `<input />` 并且`React.findDOMNode(this.refs.myInput)`通过访问它的底层DOM 节点。 Refs 是唯一一个可靠的完成这件事的实际方式。
- Refs 是为你自动管理的!如果子级被销毁了,它的ref也同样为你销毁了。这里不用担心内存(除非你做了一些疯狂的事情来自己保持一份引用)。
### 注意事项:
- *绝不* 在任何组件的 render 方法中访问 refs - 或者当任何组件的render方法还在调用栈上的任何地方运行时。
- 如果你想要保留Google Closure Compiler Crushing resilience,务必不要把指明为字符串的以属性来访问。这意味这你必须用`this.refs['myRefString']`访问,如果你的ref被定义为`ref="myRefString"`。
- 如果你没有用React写过数个程序,你的第一反应通常是打算试着用refs来在你的应用里"让事情发生"。如果是这样,花一些时间并且更精密的思考`state`应该属于组件层级的哪个位置。常常,这会变得清晰:正确的"拥有"那个属性的地方应该在层级的更高层上。把state放在那里往往消除了任何使用`ref`来 "让事情发生"的渴望 - 作为替代,数据流通常将完成你的目录。

74
docs/09-tooling-integration.zh-CN.md

@ -0,0 +1,74 @@
---
id: tooling-integration-zh-CN
title: 工具集成
permalink: tooling-integration-zh-CN.html
prev: more-about-refs-zh-CN.html
next: addons-zh-CN.html
---
每个项目使用一个不同的系统来建立和部署JavaScript.我们努力使React尽可能环境无关。
## React
### CDN-hosted React
我们提供了CDN-hosted版本的React[在我们的下载页面](/react/downloads.html).这些预构建的文件使用UMD模块格式。将他们放进一个简单的`<script>` `React` CommonJS AMD
### 使用 master
我们[在我们的 GitHub repository](https://github.com/facebook/react)有从`master`构建的说明。我们在`build/modules` 下构建了一个CommonJS模块的树,你可以把它放到任何支持CommonJS的环境或者打包工具里。
## JSX
### 浏览器中的JSX转化
如果你喜欢使用JSX,Babel提供了一个被称为browser.js的[开发用的浏览器中的 ES6 和 JSX 转换器](http://babeljs.io/docs/usage/browser/) ,它可以从`babel-core` npm release 或者[CDNJS](http://cdnjs.com/libraries/babel-core) 中 include。Include `<script type="text/babel">` 标记来使用 JSX 转换器.
> 注意:
>
> 浏览器中的JSX转换器相当大并且导致额外的本可避免的客户端计算。不要在生产环境中使用 - 见下一节。
### 投入生产: 预编译 JSX
如果你有[npm](https://www.npmjs.com/),你可以运行 `npm install -g babel`. Babel 对React v0.12 和 v0.13 有内建的支持。 标签被自动转化为它们的等价物`React.createElement(...)`, `displayName` 被自动推断并添加到所有的React.createClass 调用。
这个工具会把使用JSX语法的文件转化为简单的可直接在浏览器运行的JavaScript文件。它同样将为你监视目录并自动转化文件当他们变动时;例如:`babel --watch src/ --out-dir lib/`.
默认模式下带有`.js`后缀的JSX文件被转化。运行 `babel --help` 获取更多关于如何使用 Babel 的信息。
输出的例子:
```
$ cat test.jsx
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
React.render(<HelloMessage name="John" />, mountNode);
$ babel test.jsx
"use strict";
var HelloMessage = React.createClass({
displayName: "HelloMessage",
render: function render() {
return React.createElement(
"div",
null,
"Hello ",
this.props.name
);
}
});
React.render(React.createElement(HelloMessage, { name: "John" }), mountNode);
```
### 有帮助的开源项目
开源社区已经创建了一些集成JSX到数个编辑器和构建系统的工具。参见[JSX integrations](https://github.com/facebook/react/wiki/Complementary-Tools#jsx-integrations) 查看全部列表。

25
docs/10-addons.zh-CN.md

@ -0,0 +1,25 @@
---
id: addons-zh-CN
title: 插件
permalink: addons-zh-CN.html
prev: tooling-integration-zh-CN.html
next: animation-zh-CN.html
---
`React.addons` 是我们放置一些用来构建React apps的有用的工具的地方。 **这些应该被认为是实验性的** 但是最终批量进入核心代码或者一个有用的工具库中:
- [`TransitionGroup` 和 `CSSTransitionGroup`](animation.html), 用来处理通常不能简单实现的动画和转换,比如在组件移除之前。
- [`LinkedStateMixin`](two-way-binding-helpers.html), 简化用户的表单输入数据与组件状态的协调。
- [`cloneWithProps`](clone-with-props.html), 创建React组件的浅拷贝并改变它们的props。
- [`createFragment`](create-fragment.html), 创建一组外键的子级。
- [`update`](update.html), 一个使不可变数据在JavaScript里更易处理的辅助函数。
- [`PureRenderMixin`](pure-render-mixin.html), 一个特定情况下的性能优化器。
下面的插件只存在开发版(未压缩)React中:
- [`TestUtils`](test-utils.html), 用于写测试用例的简单的辅助工具(仅存在于未压缩版本)。
- [`Perf`](perf.html), 用于测量性能并给你提示哪里可以优化。
要获取插件,使用 `react-with-addons.js` (和它的压缩副本)而不是通常的 `react.js`
当从npm使用react包时,简单的用`require('react/addons')` 代替 `require('react')` 来获取带有所有插件的React。

252
docs/10.1-animation.zh-CN.md

@ -0,0 +1,252 @@
---
id: animation-zh-CN
title: 动画
permalink: animation-zh-CN.html
prev: addons-zh-CN.html
next: two-way-binding-helpers-zh-CN.html
---
React 提供了一个 `ReactTransitionGroup` 插件作为动画的底层API,和一个 `ReactCSSTransitionGroup` 用于轻松实现基础的CSS动画和过渡。
## 高级 API: `ReactCSSTransitionGroup`
`ReactCSSTransitionGroup` 基于 `ReactTransitionGroup` 是一个当React组件进入或离开DOM时,执行CSS动画和过渡的简单方法。它的灵感来自于杰出的 [ng-animate](http://www.nganimate.org/) 库。
### 入门指南
`ReactCSSTransitionGroup``ReactTransitions` 的接口。这是一个简单的元素,包裹了所有你感兴趣的动画组件。这里是一个淡入和淡出列表项目的例子。
```javascript{28-30}
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
var TodoList = React.createClass({
getInitialState: function() {
return {items: ['hello', 'world', 'click', 'me']};
},
handleAdd: function() {
var newItems =
this.state.items.concat([prompt('Enter some text')]);
this.setState({items: newItems});
},
handleRemove: function(i) {
var newItems = this.state.items;
newItems.splice(i, 1);
this.setState({items: newItems});
},
render: function() {
var items = this.state.items.map(function(item, i) {
return (
<div key={item} onClick={this.handleRemove.bind(this, i)}>
{item}
</div>
);
}.bind(this));
return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
<ReactCSSTransitionGroup transitionName="example" transitionEnterTimeout={500} transitionLeaveTimeout={300} >
{items}
</ReactCSSTransitionGroup>
</div>
);
}
});
```
> 注意:
>
> 你必须为`ReactCSSTransitionGroup`的所有子级提供 [ `key` 属性](/react/docs/multiple-components.html#dynamic-children),即使只渲染一个项目。这就是React将决定哪一个子级进入,离开,或者停留
在这个组件,当一个新的项目被添加到 `ReactCSSTransitionGroup` ,他将得到`example-enter` CSS类 并且在下一刻`example-enter-active` CSS类被添加。这是一个基于`transitionName` prop 的约定。
你可以使用这些类来触发CSS动画和过渡。比如,尝试添加这个CSS和添加一个新的列表项:
```css
.example-enter {
opacity: 0.01;
}
.example-enter.example-enter-active {
opacity: 1;
transition: opacity 500ms ease-in;
}
.example-leave {
opacity: 1;
}
.example-leave.example-leave-active {
opacity: 0.01;
transition: opacity 300ms ease-in;
}
```
你会注意到动画持续时间需要被同时在CSS和渲染方法里被指定;这告诉React什么时候从元素中移除动画类,并且 -- 如果它正在离开 -- 何时从DOM移除元素。
### 让初始化挂载动画
`ReactCSSTransitionGroup` 提供了可选的prop `transitionAppear`,来为在组件初始挂载添加一个额外的过渡阶段。 通常在初始化挂载时没有过渡阶段因为`transitionAppear` 的默认值为`false`。下面是一个传递`transitionAppear` 为值`true`的例子。
```javascript{3-5}
render: function() {
return (
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500}>
<h1>Fading at Initial Mount</h1>
</ReactCSSTransitionGroup>
);
}
```
在初始化挂载时 `ReactCSSTransitionGroup` 将获得`example-appear` CSS类 并且`example-appear-active` CSS 类在下一刻被添加。
```css
.example-appear {
opacity: 0.01;
transition: opacity .5s ease-in;
}
.example-appear.example-appear-active {
opacity: 1;
}
```
在初始化挂载,所有的 `ReactCSSTransitionGroup` 子级将会 `appear` 但不 `enter`。然而,所有后来添加到已存在的 `ReactCSSTransitionGroup` 的子级将 `enter` 但不 `appear`
> 注意:
>
> prop `transitionAppear` 在版本 `0.13` 被添加到 `ReactCSSTransitionGroup`。为了保持向后兼容,默认值被设置为 `false`
### 制定类
可以为你的每一步过渡使用制定类名字。代理传递一个字符串到transitionName,你可以传递一个含有`enter` 或者`leave` 类名的对象,或者一个含有 `enter`, `enter-active`, `leave-active`, 和 `leave` 类名的对象。只要提供了enter 和 leave 的类,enter-active 和 leave-active 类会被决定为后缀'-active' 到类名的尾部。这里是两个使用制定类的例子:
```javascript
...
<ReactCSSTransitionGroup
transitionName={ {
enter: 'enter',
enterActive: 'enterActive',
leave: 'leave',
leaveActive: 'leaveActive',
appear: 'appear',
appearActive: 'appearActive'
} }>
{item}
</ReactCSSTransitionGroup>
<ReactCSSTransitionGroup
transitionName={ {
enter: 'enter',
leave: 'leave',
appear: 'appear'
} }>
{item2}
</ReactCSSTransitionGroup>
...
```
### 动画组必须挂载才工作
为了使过渡效果应用到子级上,`ReactCSSTransitionGroup`必须已经挂载到了DOM或者 prop `transitionAppear` 必须被设置为 `true`。下面的例子不会工作,因为 `ReactCSSTransitionGroup` 随同新项目被挂载,而不是新项目在它内部被挂载。将这与上面的[入门指南](#入门指南)部分比较一下,看看不同。
```javascript{12-15}
render: function() {
var items = this.state.items.map(function(item, i) {
return (
<div key={item} onClick={this.handleRemove.bind(this, i)}>
<ReactCSSTransitionGroup transitionName="example">
{item}
</ReactCSSTransitionGroup>
</div>
);
}, this);
return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
{items}
</div>
);
}
```
### 动画一个或者零个项目 Animating One or Zero Items
在上面的例子中,我们渲染了一系列的项目到`ReactCSSTransitionGroup`里。然而 `ReactCSSTransitionGroup` 的子级同样可以是一个或零个项目。这使它能够动画化单个元素的进入和离开。同样,你可以动画化一个新的元素替换当前元素。例如,我们可以像这样实现一个简单的图片轮播器:
```javascript{10-12}
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
var ImageCarousel = React.createClass({
propTypes: {
imageSrc: React.PropTypes.string.isRequired
},
render: function() {
return (
<div>
<ReactCSSTransitionGroup transitionName="carousel" transitionEnterTimeout={300} transitionLeaveTimeout={300}>
<img src={this.props.imageSrc} key={this.props.imageSrc} />
</ReactCSSTransitionGroup>
</div>
);
}
});
```
### 禁用动画
如果你想,你可以禁用 `enter` 或者 `leave` 动画。例如,有时你可能想要一个 `enter` 动画,不要 `leave` 动画,但是 `ReactCSSTransitionGroup` 会在移除你的DOM节点之前等待一个动画完成。你可以添加`transitionEnter={false}` 或者 `transitionLeave={false}` props 到 `ReactCSSTransitionGroup` 来禁用这些动画。
> 注意:
>
> 当使用 `ReactCSSTransitionGroup` 时,没有办法通知你的组件何时过渡效果结束或者在动画时执行任何复杂的逻辑运算。如果你想要更多细粒度的控制,你可以使用底层的 `ReactTransitionGroup` API,它提供了你自定义过渡效果所需要的挂钩。
## 底层 API: `ReactTransitionGroup`
`ReactTransitionGroup`是动画的基础。它通过 `React.addons.TransitionGroup` 访问。当子级被声明式的从其中添加或移除(就像上面的例子)时,特殊的生命周期挂钩会在它们上面被调用。
### `componentWillAppear(callback)`
对于被初始化挂载到 `TransitionGroup` 的组件,它和 `componentDidMount()` 在相同时间被调用 。它将会阻塞其它动画发生,直到`callback`被调用。它只会在 `TransitionGroup` 初始化渲染时被调用。
### `componentDidAppear()`
在 传给`componentWillAppear` 的 `回调` 函数被调用后调用。
### `componentWillEnter(callback)`
对于被添加到已存在的 `TransitionGroup` 的组件,它和 `componentDidMount()` 在相同时间被调用 。它将会阻塞其它动画发生,直到`callback`被调用。它不会在 `TransitionGroup` 初始化渲染时被调用。
### `componentDidEnter()`
在传给 `componentWillEnter` 的`回调`函数被调用之后调用。
### `componentWillLeave(callback)`
在子级从 `ReactTransitionGroup` 中移除时调用。虽然子级被移除了,`ReactTransitionGroup` 将会保持它在DOM中,直到`callback`被调用。
### `componentDidLeave()`
在`willLeave` `callback` 被调用的时候调用(与 `componentWillUnmount` 同一时间)。
### 渲染一个不同的组件
默认情况下 `ReactTransitionGroup` 渲染为一个 `span`。你可以通过提供一个 `component` prop 来改变这种行为。例如,下面是你将如何渲染一个`<ul>`:
```javascript{1}
<ReactTransitionGroup component="ul">
...
</ReactTransitionGroup>
```
每一个React能渲染的DOM组件都是可用的。然而,`组件`不需要是一个DOM组件。它可以是任何你想要的React组件;甚至是你自己已经写好的!
> 注意:
>
> v0.12之前,当使用DOM组件时,`组件` prop 需要是一个对`React.DOM.*`的引用。既然组件简单的被传递到 `React.createElement`,它现在必然是一个字符串。复合组件必须传递工厂函数(factory)。
任何额外的、用户定义的属性将会成为已渲染的组件的属性。例如,以下是你将如何渲染一个带有css类的 `<ul>`
```javascript{1}
<ReactTransitionGroup component="ul" className="animated-list">
...
</ReactTransitionGroup>
```
Loading…
Cancel
Save