关注分离

我们在编程的时候碰到相同的功能,可以通过抽出公共方法或者类来实现复用。当我们构建新的组件的时候,尽量保持我们的组件同业务逻辑分离,将相同功能的组件抽出一个组件库,通过复用这些组件库来提高我们代码的重用性。

官方示例

构建一个头像加用户名的展示

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。在React当中,所有者就是可以设置其他组件props的组件。说的通俗点:如果组件X出现在了组件Y的render()方法中,那么组件Y就是所有者。正如我们之前所讨论的,组件不能改变props—props应同所有者初始化它们时保持一致。
一定要弄清所有者和被所有关系,父子关系的区别。所有者和被所有者关系是针对React组件的,父子关系是针对DOM结构的。来上面的例子来说,Avatar是所有者,拥有divProfilePicProfileLink,而divProfilePicProfileLink则是父子关系。

子属性

当我们创建React实例时,可以在开闭标签中添加其他的组件或者JavaScript表达式。

<Parent><Child /></Parent>

Parent可以通过this.props.children获取到它的子内容。this.props.children是不透明的:通过React.Children utilities去操作。

子调节

调节发生在React更新DOM的过程中。通常,子节点根据它们渲染的顺序调节的。看下面两个渲染示例:

// Render Pass 1
<Card>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</Card>
// Render Pass 2
<Card>
  <p>Paragraph 2</p>
</Card>

直观上看,<p> Paragraph 1</p>被移除了。实际上,React改变第一个子节点的内容,然后删除最后一个节点。React根据子节点的顺序进行调节。

带有状态的子节点

对大部分组件来说,问题不大。对跟数据保存在state当中的UI交互的组件来说,就比较麻烦了。大部分情况下元素是被隐藏而不是移除。

// Render Pass 1
<Card>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</Card>
// Render Pass 2
<Card>
  <p style={{display: 'none'}}>Paragraph 1</p>
  <p>Paragraph 2</p>
</Card>

动态子节点

当数据来自于搜索结果或者新的组件被添加到数据流里,在这种情况下,每个子节点需要保持唯一的标识。可以给每个子节点添加key属性。

var Component = React.createClass({
    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标签上。

// WRONG!
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>
    );
  }
});

// Correct :)
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>
    );
  }
});

数据流

在React当中,数据通过props从所有者向子节点传递。这就是所谓的单向数据绑定了:所有者将它拥有的组件props绑定到它的props或者state,这个过程将会递归进行。数据改变就会反映到UI层。

这节看的自己有点绕,JB得好好理理。。。


TTFB
8.4k 声望396 粉丝

技术问题不要看表象。