详解在React.js中使⽤PureComponent的重要性和使⽤⽅
⼀、介绍PureComponent
React 15.3在2016.06.29发布了,这个版本最值得关注的是⽀持了 React.PureComponent ,它取代了之前的 pure-render-mixin 。在本⽂中,我们将讨论 PureComponent 的重要性和使⽤场景。
React.PureComponent最重要的⼀个⽤处就是优化React应⽤,这很容易快速地实现。使⽤ React.PureComponent 对性能的提升是⾮常可观的,因为它减少了应⽤中的渲染次数。
PureComponent改变了⽣命周期⽅法shouldComponentupdate ,并且它会⾃动检查组件是否需要重新渲染。这时,只有PureComponent检测到 state 或者 props 发⽣变化时,PureComponent才会调⽤render ⽅法,因此,你不⽤⼿动写额外的检查,就可以在很多组件中改变state ,例如:
if (this.state.someVal !== computedVal) {
this.setState({ someVal: computedVal })
}
根据React源码,如果组件是纯组件(Pure Component),那么⼀下⽐较是很容易理解的:
if (this._compositeType === CompositeTypes.PureClass) {
shouldUpdate = !shallowEqual(prevProps, nextProps) || ! shallowEqual(inst.state, nextState);
}
其中,shadowEqual 只会"浅"检查组件的 props 和 state ,这就意味着嵌套对象和数组是不会被⽐较的。
深⽐较操作是⾮常昂贵的,同时,如果这个组件还是纯组件(PureComponent),那么深⽐较将会更浪费。另外,你也可以使⽤shouldComponentUpdate 来⼿动确定组件是否需要重新渲染。最简单的⽅式就是直接⽐较props 或 state :
shouldComponentUpdate(nextProps, nextState) {
return nextProps.user.id === props.user.id;
}
除此之外,你可以使⽤ immutable 属性。这种情况下,属性的⽐较是⾮常容易的,因为已存在的对象不会发⽣改变,取⽽代之的是重新创建新的对象。其中,就是⾮常好的Immutable库。
⼆、使⽤PureComponent
PureComponent节约了我们的时间,避免了多余的代码。那么,掌握如何正确使⽤它是⾮常重要的,否则如果使⽤不当,它就⽆法发挥作⽤。因为PureComponent仅仅是浅⽐较(shadow comparison),所以改变组件内部的props 或者 state ,它将不会发挥作⽤。例如,让我们想想这样⼀种情况,⽗组件有⼀个render⽅法和⼀个click处理⽅法:
handleClick() {
let {items} = this.state
items.push('new-item')
this.setState({ items })
}
render() {
return (
<div>
<button onClick={this.handleClick} />
<ItemList items={this.state.items} />
react to中文翻译</div>
)
}
如果ItemList是纯组件(PureComponent),那么这时它是不会被渲染的,因为尽管 this.state.items 的值发⽣了改变,但是它仍然指向同⼀个对象的引⽤。但是,通过移除可变对象就很容易改变这种情况,使之能够正确被渲染。
handleClick() {
this.setState(prevState => ({
words: at(['new-item'])
}));
}
如果⼀个纯组件(PureComponent)的 state 或 props 引⽤了⼀个新对象,那么这个组件就会被重新渲染(re-render)。这暗⽰着,如果不想损失PureComponent的优点,那么我们应该避免以下的结构:
<Entity values={this.props.values || []}/>
如上⾯代码,新数组,即便是空数组,总是会迫使组件重新渲染。为了避免这个问题,你可以使⽤defaultProps ,它包含了⼀个属性的初始化空状态。解决这个问题的另⼀种⽅法如下:
<CustomInput onChange={e => this.props.update(e.target.value)} />
在纯组件(PureComponent)被创建时,因为函数的新对象被创建了,所以它会获得新数据,并且重新渲染。解决这个问题最简单的⽅法就是: 在组件的 constructor ⽅法中使⽤ bind 。
constructor(props) {
super(props)
this.update = this.update.bind(this)
}
update(e) {
this.props.update(e.target.value)
}
render() {
return <MyInput onChange={this.update} />
}
同时,在JSX中,任何包含⼦元素(child elements)的组件,shallowEqual 检查总会返回false。
请谨记:纯组件忽略重新渲染时,不仅会影响它本⾝,⽽且会影响它的说有⼦元素,所以,使⽤PureComponent的最佳情况就是展⽰组件,它既没有⼦组件,也没有依赖应⽤的全局状态。
三、总结
事实上,如果你已经意识到shallowEqual 和 JS References 的特性,过渡到PureComponent是相当容易的。正常情况下,迁移的⽅式⾮常简单,就像改变组件继承的基类,从
class MyComponent extends Component {...}
class MyComponent extends PureComponent {...}
这样不仅能平滑过渡,甚⾄可以提升性能。所以,我极⼒推荐所有⼈在开发应⽤中使⽤PureComponent。
四、注意
在纯组件有⼦组件的时候,所有基于 t 改变的⼦组件,,除⾮在⽗组件(Parent ParentComponent)中声明contextTypes 。
本⽂翻译⾄。
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。