@brizer
2016-01-29T23:10:05.000000Z
字数 2226
阅读 1340
前面的学习中也对组件进行过拼装,这次来回顾和加深一下。
后面也简单介绍了Virtual DOM的机制。
先看看Facebook 的一个组件实例:
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,组件不能修改自己的props。
我们通过props.children来读取子级。例如:
<Parent><Child /></Parent>
Parent就可以通过专门的this.props.children
来读取Child。
每次render方法调用后,React会更新DOM,这个过程叫做校正。
子级会根据它们被渲染的顺序来校正,对于大多数组件而言,这无所谓。但是对于使用this.state的状态化组件,这样做会存在很大的问题。
如果子级要在多个渲染阶段保持自己的特征和状态,我们就需要用唯一标识key
来区分。
render: function() {
var results = this.props.results;
return (
<ol>
{results.map(function(result) {
return <li key={result.id}>{result.text}</li>;
})}
</ol>
);
}
key在virtualDOM的diff算法时起到关键性的作用。
我们需要一点就是把key添加到子级组件本身上,而不是每个子级内部的HTML上,举个例子:
// 错误!
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>
);
}
});
如果我们使用32位无符号数字作为key的属性,就会发生混乱,因为数字会按大小并且排序到其他属性前面。所以我们最好是在key前面加一个字符串前缀来避免:
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>
);
}
virtual DOM 的操作, 不保证马上就会产生真实的效果。这样就使得 React 能够等到事件循环的结尾, 而在之前完全不用操作真实的DOM。
在这基础上, React 计算出几乎最小的 diff, 以最小的步骤将 diff 作用到真实的 DOM 上。批量处理 DOM 操作和作用最少的 diff 是应用自身都能做到的。任何应用做了这个, 都能变得跟 React 一样地高效。但人工处理出来非常繁琐, 而且容易出错. React 可以替你做到。