[关闭]
@brizer 2016-01-29T23:10:05.000000Z 字数 2226 阅读 1309

React之组件拼装


前言

前面的学习中也对组件进行过拼装,这次来回顾和加深一下。
后面也简单介绍了Virtual DOM的机制。


实例

先看看Facebook 的一个组件实例:

  1. var Avatar = React.createClass({
  2. render: function() {
  3. return (
  4. <div>
  5. <ProfilePic username={this.props.username} />
  6. <ProfileLink username={this.props.username} />
  7. </div>
  8. );
  9. }
  10. });
  11. var ProfilePic = React.createClass({
  12. render: function() {
  13. return (
  14. <img src={'http://graph.facebook.com/' + this.props.username + '/picture'} />
  15. );
  16. }
  17. });
  18. var ProfileLink = React.createClass({
  19. render: function() {
  20. return (
  21. <a href={'http://www.facebook.com/' + this.props.username}>
  22. {this.props.username}
  23. </a>
  24. );
  25. }
  26. });
  27. React.render(
  28. <Avatar username="pwh" />,
  29. document.getElementById('example')
  30. );

通过之前做过的评论框组件,我们应该可以看出,Avatar组件拥有子组件ProfilePic和ProfileLink。父亲的属性会成为子组件的props,组件不能修改自己的props。


props.children

我们通过props.children来读取子级。例如:

  1. <Parent><Child /></Parent>

Parent就可以通过专门的this.props.children来读取Child。


key

每次render方法调用后,React会更新DOM,这个过程叫做校正
子级会根据它们被渲染的顺序来校正,对于大多数组件而言,这无所谓。但是对于使用this.state的状态化组件,这样做会存在很大的问题。

如果子级要在多个渲染阶段保持自己的特征和状态,我们就需要用唯一标识key来区分。

  1. render: function() {
  2. var results = this.props.results;
  3. return (
  4. <ol>
  5. {results.map(function(result) {
  6. return <li key={result.id}>{result.text}</li>;
  7. })}
  8. </ol>
  9. );
  10. }

key在virtualDOM的diff算法时起到关键性的作用。
我们需要一点就是把key添加到子级组件本身上,而不是每个子级内部的HTML上,举个例子:

  1. // 错误!
  2. var ListItemWrapper = React.createClass({
  3. render: function() {
  4. return <li key={this.props.data.id}>{this.props.data.text}</li>;
  5. }
  6. });
  7. var MyComponent = React.createClass({
  8. render: function() {
  9. return (
  10. <ul>
  11. {this.props.results.map(function(result) {
  12. return <ListItemWrapper data={result}/>;
  13. })}
  14. </ul>
  15. );
  16. }
  17. });
  18. // 正确 :)
  19. var ListItemWrapper = React.createClass({
  20. render: function() {
  21. return <li>{this.props.data.text}</li>;
  22. }
  23. });
  24. var MyComponent = React.createClass({
  25. render: function() {
  26. return (
  27. <ul>
  28. {this.props.results.map(function(result) {
  29. return <ListItemWrapper key={result.id} data={result}/>;
  30. })}
  31. </ul>
  32. );
  33. }
  34. });

如果我们使用32位无符号数字作为key的属性,就会发生混乱,因为数字会按大小并且排序到其他属性前面。所以我们最好是在key前面加一个字符串前缀来避免:

  1. render: function() {
  2. var items = {};
  3. this.props.results.forEach(function(result) {
  4. // 如果 result.id 看起来是一个数字(比如短哈希),那么
  5. // 对象字面量的顺序就得不到保证。这种情况下,需要添加前缀
  6. // 来确保 key 是字符串。
  7. items['result-' + result.id] = <li>{result.text}</li>;
  8. });
  9. return (
  10. <ol>
  11. {items}
  12. </ol>
  13. );
  14. }

virtualDOM

virtual DOM 的操作, 不保证马上就会产生真实的效果。这样就使得 React 能够等到事件循环的结尾, 而在之前完全不用操作真实的DOM。

在这基础上, React 计算出几乎最小的 diff, 以最小的步骤将 diff 作用到真实的 DOM 上。批量处理 DOM 操作和作用最少的 diff 是应用自身都能做到的。任何应用做了这个, 都能变得跟 React 一样地高效。但人工处理出来非常繁琐, 而且容易出错. React 可以替你做到。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注