Keyed Fragments with Dynamic Children
目录:
React官方解释:
官方建议&第三方建议:
// 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> ); } });
//Not Good var Swapper = React.createClass({ propTypes: { // `leftChildren` and `rightChildren` can be a string,element,array,etc. leftChildren: React.PropTypes.node,rightChildren: React.PropTypes.node,swapped: React.PropTypes.bool } render: function() { var children; if (this.props.swapped) { children = [this.props.rightChildren,this.props.leftChildren]; } else { children = [this.props.leftChildren,this.props.rightChildren]; } return <div>{children}</div>; } }); //Right if (this.props.swapped) { children = React.addons.createFragment({ right: this.props.rightChildren,left: this.props.leftChildren }); } else { children = React.addons.createFragment({ left: this.props.leftChildren,right: this.props.rightChildren }); } It is often easier and wiser to move the state higher in component hierarchy 浅层思考:
render() { return ( <div> {this.state.data.map(function(result,index) { return <DivItem data={result}/>; })} <div></div> <div></div> </div> ); }; render() { return ( <div> <div> {this.state.data.map(function(result,index) { return <DivItem data={result}/>; })} </div> <div></div> <div></div> </div> ); }; 这也是一个神奇效果,同级的div节点,通过循环产生的react-id和其他的并不是同级效果,不过仔细观察数据,也是很好理解的。观察react-id我们也可以发现,在没有外包直接父级别节点的情况下,通过循环产生的节点应该会有一个“虚拟父节点”,这时候的react-id和同层次的节点已经不一样,同时又不同于真正存在父节点的情况
// Wrong class ListItem extends Component { ··· render () { return ( <li key={this.props.data.id}>{this.props.data.text}</li> ); } } class HelloDemo extends Component { ··· render() { return ( <ul> {this.state.data.map(function(result) { return <ListItem data={result}/>; })} </ul> ); }; } // Right class ListItem extends Component { ··· render () { return ( <li>{this.props.data.text}</li> ); } } class HelloDemo extends Component { ··· render() { return ( <ul> {this.state.data.map(function(result) { return <ListItem key={result.id} data={result}/>; })} </ul> ); }; } 即使没有key,或者错误使用key,react也能返回react-id,同时有一些警告,当然,错误使用key,结果和没有key是一样的,具体会有什么样的差别,下面会深究
// Wrong render() { let line = [<span>道士下山</span>,<span>捉妖记</span>]; return ( <ul> {line} </ul> ); } // Right import Addons from "react/addons"; ... render() { let line = Addons.addons.createFragment({ daoshi: <span>道士下山</span>,zhuoyao: <span>捉妖记</span> }); return ( <ul> {line} </ul> ); }; 效果也是可以猜到的
render() { return ( <ul> {this.state.data.map(function(result) { return <ListItem key='1' data={result}/>; })} </ul> ); };
探究:上面讲了半天,也是周四下午我和刘晶、罗黎讨论的主要内容,key无疑会影响到react-id的生成方式,但我们关心的是这到底有什么影响??我们以后写代码要注意什么?? 增加节点和删除节点的功能类似,这里仅以增加节点的代码为例://公用方法,在最前面添加一个节点 handleClick() { let data = this.state.data; data.unshift({id:10,text: '盗梦空间'}); this.setState(data); }; //不添加key render() { return ( <ul onClick={this.handleClick.bind(this)}> {this.state.data.map(function(result,index) { return <ListItem data={result}/>; })} </ul> ); }; //key为index render() { return ( <ul onClick={this.handleClick.bind(this)}> {this.state.data.map(function(result,index) { return <ListItem key={index} data={result}/>; })} </ul> ); }; //key为特定唯一值 render() { return ( <ul onClick={this.handleClick.bind(this)}> {this.state.data.map(function(result,index) { return <ListItem key={result.id} data={result}/>; })} </ul> ); }; 从结果我们已经非常容易看出来。当在一列数据的最前放添加数据时,他们对于节点的处理情况是不同的。
再举替换的例子// 替换部分 handleClick() { let data = this.state.data; [data[0],data[3]] = [data[3],data[0]]; this.setState(data); }; 我们知道react当中,即使是相同的组件,当key发生改变的时候,React也会直接跳过Dom diff,完全弃置之前组件的所有子元素,从头重新开始渲染。上面的例子其实引出一点小问题,如果交换元素的时候,仅仅替换内容是不是更快?也就是前者的替换方式可能要优于后者? 这里想出三个解释:
个人建议:
相关参考:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |