详解在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.js 就是非常好的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} /> </div> ) }
如果itemlist是纯组件(purecomponent),那么这时它是不会被渲染的,因为尽管 this.state.items
的值发生了改变,但是它仍然指向同一个对象的引用。但是,通过移除可变对象就很容易改变这种情况,使之能够正确被渲染。
handleclick() { this.setstate(prevstate => ({ words: prevstate.items.concat(['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。
四、注意
在纯组件有子组件的时候,所有基于 this.context 改变的子组件, ,除非在父组件(parent parentcomponent)中声明 contexttypes 。
本文翻译至。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: 文件批量生成IO流读写