关注分离
我们在编程的时候碰到相同的功能,可以通过抽出公共方法或者类来实现复用。当我们构建新的组件的时候,尽量保持我们的组件同业务逻辑分离,将相同功能的组件抽出一个组件库,通过复用这些组件库来提高我们代码的重用性。
官方示例
构建一个头像加用户名的展示
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是所有者,拥有div、ProfilePic、ProfileLink,而div和ProfilePic、ProfileLink则是父子关系。
子属性
当我们创建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得好好理理。。。