@brizer
2016-01-29T15:10:05.000000Z
字数 2226
阅读 1431
前面的学习中也对组件进行过拼装,这次来回顾和加深一下。
后面也简单介绍了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 可以替你做到。