mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Add Chinese translation to 7 more pages.
Translate 'Note' to '注意' instead of '提示' to make it more sensible.
This commit is contained in:
@@ -41,7 +41,7 @@ React.render(myElement, document.body);
|
||||
|
||||
React 的 JSX 里约定分别使用首字母大、小写来区分本地组件的类和 HTML 标签。
|
||||
|
||||
> 提示:
|
||||
> 注意:
|
||||
>
|
||||
> 由于 JSX 就是 JavaScript,一些标识符像 `class` 和 `for` 不建议作为 XML
|
||||
> 属性名。作为替代,React DOM 使用 `className` 和 `htmlFor` 来做对应的属性。
|
||||
@@ -79,7 +79,7 @@ var app = React.createElement(
|
||||
|
||||
如果你要使用 JSX,这篇 [新手入门](/react/docs/getting-started.html) 教程来教你如何搭建环境。
|
||||
|
||||
> 提示:
|
||||
> 注意:
|
||||
>
|
||||
> JSX 表达式总是会当作 ReactElement 执行。具体的实际细节可能不同。一种优化
|
||||
> 的模式是把 ReactElement 当作一个行内的对象字面量形式来绕过
|
||||
@@ -135,6 +135,6 @@ var content = (
|
||||
);
|
||||
```
|
||||
|
||||
> 提示:
|
||||
> 注意:
|
||||
>
|
||||
> JSX 类似于 HTML,但不完全一样。参考 [JSX 陷阱](/react/docs/jsx-gotchas.html) 了解主要不同。
|
||||
|
||||
@@ -8,7 +8,7 @@ next: interactivity-and-dynamic-uis-zh-CN.html
|
||||
|
||||
JSX 与 HTML 非常相似,但是有些关键区别要注意。
|
||||
|
||||
> 提示:
|
||||
> 注意:
|
||||
>
|
||||
> 关于 DOM 的区别,如行内样式属性 `style`,参考 [DOM 区别](/react/docs/dom-differences.html)
|
||||
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
---
|
||||
id: multiple-componentsm-zh-CN
|
||||
title: 复合组件
|
||||
permalink: multiple-components-zh-CN.html
|
||||
prev: interactivity-and-dynamic-uis-zh-CN.html
|
||||
next: reusable-components-zh-CN.html
|
||||
---
|
||||
|
||||
目前为止,我们已经学了如何用单个组件来展示数据和处理用户输入。下一步让我们来体验 React 最激动人心的特性之一:可组合性(composability)。
|
||||
|
||||
|
||||
## 动机:关注分离
|
||||
|
||||
通过复用那些接口定义良好的组件来开发新的模块化组件,我们得到了与使用函数和类相似的好处。具体来说就是能够通过开发简单的组件把程序的*不同关注面分离*。如果为程序开发一套自定义的组件库,那么就能以最适合业务场景的方式来展示你的用户界面。
|
||||
|
||||
## 组合实例
|
||||
|
||||
一起来使用 Facebook Graph API 开发显示个人图片和用户名的简单 Avatar 组件吧。
|
||||
|
||||
```javascript
|
||||
var Avatar = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<ProfilePic username={this.props.username} />
|
||||
<ProfileLink username={this.props.username} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ProfilePic = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<img src={'http://graph.facebook.com/' + this.props.username + '/picture'} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ProfileLink = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<a href={'http://www.facebook.com/' + this.props.username}>
|
||||
{this.props.username}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.render(
|
||||
<Avatar username="pwh" />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## 从属关系
|
||||
|
||||
上面例子中,`Avatar` 拥有 `ProfilePic` 和 `ProfileLink` 的实例。`拥有者` 就是给其它组件设置 `props` 的那个组件。更正式地说,
|
||||
如果组件 `Y` 在 `render()` 方法是创建了组件 `X`,那么 `Y` 就拥有 `X`。上面讲过,组件不能修改自身的 `props` - 它们总是与它们拥有者设置的保持一致。这是保持用户界面一致性的关键性原则。
|
||||
|
||||
把从属关系与父子关系加以区别至关重要。从属关系是 React 特有的,父子关系与你所熟知的 DOM 里的是一样的。在上一个例子中,`Avatar` 拥有 `div`、`ProfilePic` 和 `ProfileLink` 实例,`div` 是 `ProfilePic` 和 `ProfileLink` 实例的**父级**(但不是拥有者)。
|
||||
|
||||
|
||||
## 子级
|
||||
|
||||
实例化 React 组件时,可以在标签开始和关闭的位置包含其它 React 组件:
|
||||
|
||||
```javascript
|
||||
<Parent><Child /></Parent>
|
||||
```
|
||||
|
||||
`Parent` 能通过专门的 `this.props.children` props 读取子级。**`this.props.children` 是一个不透明的数据结构:** 通过 [React.Children 工具类](/react/docs/top-level-api.html#react.children) 来操作。
|
||||
|
||||
### 子级校正(Reconciliation)
|
||||
|
||||
**校正就是每次 render 方法调用后 React 更新 DOM 的过程。** 一般情况下,子级会根据它们被渲染的顺序来做校正。例如,下面代码描述了两次渲染的过程:
|
||||
|
||||
```html
|
||||
// 第一次渲染
|
||||
<Card>
|
||||
<p>Paragraph 1</p>
|
||||
<p>Paragraph 2</p>
|
||||
</Card>
|
||||
// 第二次渲染
|
||||
<Card>
|
||||
<p>Paragraph 2</p>
|
||||
</Card>
|
||||
```
|
||||
|
||||
直观来看,只是删除了`<p>Paragraph 1</p>`。事实上,React 先更新第一个子级的内容,然后删除最后一个组件。React 是根据子级的*顺序*来校正的。
|
||||
|
||||
### 状态化子级
|
||||
|
||||
对于大多数组件,这没什么大碍。但是,对于使用 `this.state` 来在多次渲染过程中里维持数据的状态化组件,这样做潜在很多问题。
|
||||
|
||||
多数情况下,可以通过隐藏组件而不是删除它们来绕过这些问题。
|
||||
|
||||
```html
|
||||
// 第一次渲染
|
||||
<Card>
|
||||
<p>Paragraph 1</p>
|
||||
<p>Paragraph 2</p>
|
||||
</Card>
|
||||
// 第二次渲染
|
||||
<Card>
|
||||
<p style={{'{{'}}display: 'none'}}>Paragraph 1</p>
|
||||
<p>Paragraph 2</p>
|
||||
</Card>
|
||||
```
|
||||
|
||||
### 动态子级
|
||||
|
||||
如果子级被打乱(如在搜索结果中)或者有新组件添加到列表开头(如在流中)情况会变得更加复杂。如果子级要在多个渲染阶段保持自己的特征和状态,在这种情况下,你可以通过给子级设置惟一的 `key` 来区分。
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
var results = this.props.results;
|
||||
return (
|
||||
<ol>
|
||||
{results.map(function(result) {
|
||||
return <li key={result.id}>{result.text}</li>;
|
||||
})}
|
||||
</ol>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
当 React 校正带有 key 的子级时,它会确保它们被重新排序(而不是破坏)或者删除(而不是重用)。
|
||||
`务必` 把 `key` 添加到子级数组里组件本身上,而不是每个子级内部最外层 HTML 上:
|
||||
|
||||
```javascript
|
||||
// 错误!
|
||||
var ListItemWrapper = React.createClass({
|
||||
render: function() {
|
||||
return <li key={this.props.data.id}>{this.props.data.text}</li>;
|
||||
}
|
||||
});
|
||||
var MyComponent = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<ul>
|
||||
{this.props.results.map(function(result) {
|
||||
return <ListItemWrapper data={result}/>;
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// 正确 :)
|
||||
var ListItemWrapper = React.createClass({
|
||||
render: function() {
|
||||
return <li>{this.props.data.text}</li>;
|
||||
}
|
||||
});
|
||||
var MyComponent = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<ul>
|
||||
{this.props.results.map(function(result) {
|
||||
return <ListItemWrapper key={result.id} data={result}/>;
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
也可以传递 object 来做有 key 的子级。object 的 key 会被当作每个组件的 `key`。但是一定要牢记 JavaScript 并不总是保证属性的顺序会被保留。实际情况下浏览器一般会保留属性的顺序,**除了** 使用 32位无符号数字做为 key 的属性。数字型属性会按大小排序并且排在其它属性前面。一旦发生这种情况,React 渲染组件的顺序就是混乱。可能在 key 前面加一个字符串前缀来避免:
|
||||
|
||||
```javascript
|
||||
render: function() {
|
||||
var items = {};
|
||||
|
||||
this.props.results.forEach(function(result) {
|
||||
// 如果 result.id 看起来是一个数字(比如短哈希),那么
|
||||
// 对象字面量的顺序就得不到保证。这种情况下,需要添加前缀
|
||||
// 来确保 key 是字符串。
|
||||
items['result-' + result.id] = <li>{result.text}</li>;
|
||||
});
|
||||
|
||||
return (
|
||||
<ol>
|
||||
{items}
|
||||
</ol>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 数据流
|
||||
|
||||
React 里,数据通过上面介绍过的 `props` 从拥有者流向归属者。这就是高效的单向数据绑定(one-way data binding):拥有者通过它的 `props` 或 `state` 计算出一些值,并把这些值绑定到它们拥有的组件的 props 上。因为这个过程会递归地调用,所以数据变化会自动在所有被使用的地方自动反映出来。
|
||||
|
||||
|
||||
## 性能提醒
|
||||
|
||||
你或许会担心如果一个拥有者有大量子级时,对于数据变化做出响应非常耗费性能。值得庆幸的是执行 JavaScript 非常的快,而且 `render()` 方法一般比较简单,所以在大部分应用里这样做速度极快。此外,性能的瓶颈大多是因为 DOM 更新,而非 JS 执行,而且 React 会通过批量更新和变化检测来优化性能。
|
||||
|
||||
但是,有时候需要做细粒度的性能控制。这种情况下,可以重写 `shouldComponentUpdate()` 方法返回 false 来让 React 跳过对子树的处理。参考 [React reference docs](/react/docs/component-specs.html) 了解更多。
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 如果在数据变化时让 `shouldComponentUpdate()` 返回 false,React 就不能保证用户界面同步。当使用它的时候一定确保你清楚到底做了什么,并且只在遇到明显性能问题的时候才使用它。不要低估 JavaScript 的速度,DOM 操作通常才是慢的原因。
|
||||
@@ -0,0 +1,184 @@
|
||||
---
|
||||
id: reusable-components-zh-CN
|
||||
title: 可复用组件
|
||||
permalink: reusable-components-zh-CN.html
|
||||
prev: multiple-components-zh-CN.html
|
||||
next: transferring-props-zh-CN.html
|
||||
---
|
||||
|
||||
设计接口的时候,把通用的设计元素(按钮,表单框,布局组件等)拆成接口良好定义的可复用的组件。这样,下次开发相同界面程序时就可以写更少的代码,也意义着更高的开发效率,更少的 Bug 和更少的程序体积。
|
||||
|
||||
|
||||
## Prop 验证
|
||||
|
||||
随着应用不断变大,保证组件被正确使用变得非常有用。为此我们引入 `propTypes`。`React.PropTypes` 提供很多验证器 (validator) 来验证传入数据的有效性。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。注意为了性能考虑,只在开发环境验证 `propTypes`。下面用例子来说明不同验证器的区别:
|
||||
|
||||
```javascript
|
||||
React.createClass({
|
||||
propTypes: {
|
||||
// 可以声明 prop 为指定的 JS 基本类型。默认
|
||||
// 情况下,这些 prop 都是可传可不传的。
|
||||
optionalArray: React.PropTypes.array,
|
||||
optionalBool: React.PropTypes.bool,
|
||||
optionalFunc: React.PropTypes.func,
|
||||
optionalNumber: React.PropTypes.number,
|
||||
optionalObject: React.PropTypes.object,
|
||||
optionalString: React.PropTypes.string,
|
||||
|
||||
// 所有可以被渲染的对象:数字,
|
||||
// 字符串,DOM 元素或包含这些类型的数组。
|
||||
optionalNode: React.PropTypes.node,
|
||||
|
||||
// React 元素
|
||||
optionalElement: React.PropTypes.element,
|
||||
|
||||
// 用 JS 的 instanceof 操作符声明 prop 为类的实例。
|
||||
optionalMessage: React.PropTypes.instanceOf(Message),
|
||||
|
||||
// 用 enum 来限制 prop 只接受指定的值。
|
||||
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
|
||||
|
||||
// 指定的多个对象类型中的一个
|
||||
optionalUnion: React.PropTypes.oneOfType([
|
||||
React.PropTypes.string,
|
||||
React.PropTypes.number,
|
||||
React.PropTypes.instanceOf(Message)
|
||||
]),
|
||||
|
||||
// 指定类型组成的数组
|
||||
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
|
||||
|
||||
// 指定类型的属性构成的对象
|
||||
optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
|
||||
|
||||
// 特定形状参数的对象
|
||||
optionalObjectWithShape: React.PropTypes.shape({
|
||||
color: React.PropTypes.string,
|
||||
fontSize: React.PropTypes.number
|
||||
}),
|
||||
|
||||
// 以后任意类型加上 `isRequired` 来使 prop 不可空。
|
||||
requiredFunc: React.PropTypes.func.isRequired,
|
||||
|
||||
// 不可空的任意类型
|
||||
requiredAny: React.PropTypes.any.isRequired,
|
||||
|
||||
// 自定义验证器。如果验证失败需要返回一个 Error 对象。不要直接
|
||||
// 使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。
|
||||
customProp: function(props, propName, componentName) {
|
||||
if (!/matchme/.test(props[propName])) {
|
||||
return new Error('Validation failed!');
|
||||
}
|
||||
}
|
||||
},
|
||||
/* ... */
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## 默认 Prop 值
|
||||
|
||||
React 支持以声明式的方式来定义 `props` 的默认值。
|
||||
|
||||
```javascript
|
||||
var ComponentWithDefaultProps = React.createClass({
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
value: 'default value'
|
||||
};
|
||||
}
|
||||
/* ... */
|
||||
});
|
||||
```
|
||||
|
||||
当父级没有传入 props 时,`getDefaultProps()` 可以保证 `this.props.value` 有默认值,注意 `getDefaultProps` 的结果会被 *缓存*。得益于此,你可以直接使用 props,而不必写手动编写一些重复或无意义的代码。
|
||||
|
||||
## 传递 Props:小技巧
|
||||
|
||||
有一些常用的 React 组件只是对 HTML 做简单扩展。通常,你想少写点代码来把传入组件的 props 复制到对应的 HTML 元素上。这时 JSX 的 _spread_ 语法会帮到你:
|
||||
|
||||
```javascript
|
||||
var CheckLink = React.createClass({
|
||||
render: function() {
|
||||
// 这样会把 CheckList 所有的 props 复制到 <a>
|
||||
return <a {...this.props}>{'√ '}{this.props.children}</a>;
|
||||
}
|
||||
});
|
||||
|
||||
React.render(
|
||||
<CheckLink href="/checked.html">
|
||||
Click here!
|
||||
</CheckLink>,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
## 单个子级
|
||||
|
||||
`React.PropTypes.element` 可以限定只能有一个子级传入。
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({
|
||||
propTypes: {
|
||||
children: React.PropTypes.element.isRequired
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.children} // 只能有一个元素,否则会抛异常。
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## Mixins
|
||||
|
||||
组件是 React 里复用代码最佳方式,但是有时一些复杂的组件间也需要共用一些功能。有时会被称为 [跨切面关注点](http://en.wikipedia.org/wiki/Cross-cutting_concern)。React 使用 `mixins` 来解决这类问题。
|
||||
|
||||
一个通用的场景是:一个组件需要定期更新。用 `setInterval()` 做很容易,但当不需要它的时候取消定时器来节省内存是非常重要的。React 提供 [生命周期方法](/react/docs/working-with-the-browser.html#component-lifecycle) 来告知组件创建或销毁的时间。下面来做一个简单的 mixin,使用 `setInterval()` 并保证在组件销毁时清理定时器。
|
||||
|
||||
```javascript
|
||||
var SetIntervalMixin = {
|
||||
componentWillMount: function() {
|
||||
this.intervals = [];
|
||||
},
|
||||
setInterval: function() {
|
||||
this.intervals.push(setInterval.apply(null, arguments));
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
this.intervals.map(clearInterval);
|
||||
}
|
||||
};
|
||||
|
||||
var TickTock = React.createClass({
|
||||
mixins: [SetIntervalMixin], // 引用 mixin
|
||||
getInitialState: function() {
|
||||
return {seconds: 0};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.setInterval(this.tick, 1000); // 调用 mixin 的方法
|
||||
},
|
||||
tick: function() {
|
||||
this.setState({seconds: this.state.seconds + 1});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<p>
|
||||
React has been running for {this.state.seconds} seconds.
|
||||
</p>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.render(
|
||||
<TickTock />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
关于 mixin 值得一提的优点是,如果一个组件使用了多个 mixin,并用有多个 mixin 定义了同样的生命周期方法(如:多个 mixin 都需要在组件销毁时做资源清理操作),所有这些生命周期方法都保证会被执行到。方法执行顺序是:首先按 mixin 引入顺序执行 mixin 里方法,最后执行组件内定义的方法。
|
||||
@@ -0,0 +1,163 @@
|
||||
---
|
||||
id: transferring-props-zh-CN
|
||||
title: 传递 Props
|
||||
permalink: transferring-props-zh-CN.html
|
||||
prev: reusable-components-zh-CN.html
|
||||
next: forms-zh-CN.html
|
||||
---
|
||||
|
||||
React 里有一个非常常用的模式就是对组件做一层抽象。组件对外公开一个简单的属性(Props)来实现功能,但内部细节可能有非常复杂的实现。
|
||||
|
||||
可以使用 [JSX 展开属性](/react/docs/jsx-spread-zh-CN.html) 来合并现有的 props 和其它值:
|
||||
|
||||
```javascript
|
||||
return <Component {...this.props} more="values" />;
|
||||
```
|
||||
|
||||
如果不使用 JSX,可以使用一些对象辅助方法如 ES6 的 `Object.assign` 或 Underscore `_.extend`。
|
||||
|
||||
```javascript
|
||||
return Component(Object.assign({}, this.props, { more: 'values' }));
|
||||
```
|
||||
|
||||
下面的教程介绍一些最佳实践。使用了 JSX 和 ES7 的还在试验阶段的特性。
|
||||
|
||||
|
||||
## 手动传递
|
||||
|
||||
大部分情况下你应该显式地向下传递 props。这样可以确保只公开你认为是安全的内部 API 的子集。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
<div className={fancyClass} onClick={this.props.onClick}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
React.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
</FancyCheckbox>,
|
||||
document.body
|
||||
);
|
||||
```
|
||||
|
||||
但 `name` 这个属性怎么办?还有 `title`、`onMouseOver` 这些 props?
|
||||
|
||||
|
||||
## 在 JSX 里使用 `...` 传递
|
||||
|
||||
有时把所有属性都传下去是不安全或啰嗦的。这时可以使用 [解构赋值](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) 中的剩余属性特性来把未知属性批量提取出来。
|
||||
|
||||
列出所有要当前使用的属性,后面跟着 `...other`。
|
||||
|
||||
```javascript
|
||||
var { checked, ...other } = this.props;
|
||||
```
|
||||
|
||||
这样能确保把所有 props 传下去,*除了* 那些已经被使用了的。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// `other` 包含 { onClick: console.log } 但 checked 属性除外
|
||||
return (
|
||||
<div {...other} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
React.render(
|
||||
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
|
||||
Hello world!
|
||||
</FancyCheckbox>,
|
||||
document.body
|
||||
);
|
||||
```
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 上面例子中,`checked` 属性也是一个有效的 DOM 属性。如果你没有使用解构赋值,那么可能无意中把它传下去。
|
||||
|
||||
在传递这些未知的 `other` 属性时,要经常使用解构赋值模式。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
// 反模式:`checked` 会被传到里面的组件里
|
||||
return (
|
||||
<div {...this.props} className={fancyClass} />
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## 使用和传递同一个 Prop
|
||||
|
||||
如果组件需要使用一个属性又要往下传递,可以直接使用 `checked={checked}` 再传一次。这样做比传整个 `this.props` 对象要好,因为更利于重构和语法检查。
|
||||
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var { checked, title, ...other } = this.props;
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
|
||||
return (
|
||||
<label>
|
||||
<input {...other}
|
||||
checked={checked}
|
||||
className={fancyClass}
|
||||
type="checkbox"
|
||||
/>
|
||||
{fancyTitle}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 顺序很重要,把 `{...other}` 放到 JSX props 前面会使它不被覆盖。上面例子中我们可以保证 input 的 type 是 `"checkbox"`。
|
||||
|
||||
|
||||
## 剩余属性和展开属性 `...`
|
||||
|
||||
剩余属性可以把对象剩下的属性提取到一个新的对象。会把所有在解构赋值中列出的属性剔除。
|
||||
|
||||
这是 [ES7 草案](https://github.com/sebmarkbage/ecmascript-rest-spread) 中的试验特性。
|
||||
|
||||
```javascript
|
||||
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
|
||||
x; // 1
|
||||
y; // 2
|
||||
z; // { a: 3, b: 4 }
|
||||
```
|
||||
|
||||
> 注意:
|
||||
>
|
||||
> 使用 [JSX 命令行工具](http://npmjs.org/package/react-tools) 配合 `--harmony` 标记来启用 ES7 语法。
|
||||
|
||||
|
||||
## 使用 Underscore 来传递
|
||||
|
||||
如果不使用 JSX,可以使用一些库来实现相同效果。Underscore 提供 `_.omit` 来过滤属性,`_.extend` 复制属性到新的对象。
|
||||
```javascript
|
||||
var FancyCheckbox = React.createClass({
|
||||
render: function() {
|
||||
var checked = this.props.checked;
|
||||
var other = _.omit(this.props, 'checked');
|
||||
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
|
||||
return (
|
||||
React.DOM.div(_.extend({}, other, { className: fancyClass }))
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
id: complementary-tools-zh-CN
|
||||
title: 补充工具
|
||||
permalink: complementary-tools-zh-CN.html
|
||||
prev: videos-zh-CN.html
|
||||
next: examples-zh-CN.html
|
||||
---
|
||||
|
||||
本页被移到了 [GitHub wiki](https://github.com/facebook/react/wiki/Complementary-Tools)。
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
id: examples-zh-CN
|
||||
title: 示例
|
||||
permalink: examples-zh-CN.html
|
||||
prev: complementary-tools-zh-CN.html
|
||||
---
|
||||
|
||||
本页被移到了 [GitHub wiki](https://github.com/facebook/react/wiki/Examples)。
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
id: flux-overview-zh-CN
|
||||
title: Flux 应用架构
|
||||
---
|
||||
|
||||
本页被移到了 Flux 网站。[点击访问](http://facebook.github.io/flux/docs/overview.html)。
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
id: flux-todo-list-zh-CN
|
||||
title: Flux TodoMVC 教程
|
||||
---
|
||||
|
||||
本页被移到了 Flux 网站。[点击访问](http://facebook.github.io/flux/docs/todo-list.html)。
|
||||
Reference in New Issue
Block a user