扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
PureComponent如何在React中使用?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
创新互联公司是一家集网站建设,柳北企业网站建设,柳北品牌网站建设,网站定制,柳北网站建设报价,网络营销,网络优化,柳北网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
React避免重复渲染
React在渲染出的UI内部建立和维护了一个内层的实现方式,它包括了从组件返回的React元素。这种实现方式使得React避免了一些不必要的创建和关联DOM节点,因为这样做可能比直接操作JavaScript对象更慢一些,它被称之为“虚拟DOM”。
当一个组件的props或者state改变时,React通过比较新返回的元素和之前渲染的元素来决定是否有必要更新实际的DOM。当他们不相等时,React会更新DOM。
在一些情况下,你的组件可以通过重写这个生命周期函数shouldComponentUpdate来提升速度, 它是在重新渲染过程开始前触发的。 这个函数默认返回true,可使React执行更新:
shouldComponentUpdate(nextProps, nextState) { return true; }
举例
如果想让组件只在props.color
或者state.count
的值变化时重新渲染,你可以像下面这样设定shouldComponentUpdate
:
class CounterButton extends React.Component { constructor(props) { super(props); this.state = {count: 1}; } shouldComponentUpdate(nextProps, nextState) { if (this.props.color !== nextProps.color) { return true; } if (this.state.count !== nextState.count) { return true; } return false; } render() { return ( ); } }
在以上代码中,shouldComponentUpdate
只检查props.color
和state.count
的变化。如果这些值没有变化,组件就不会更新。当你的组件变得更加复杂时,你可以使用类似的模式来做一个“浅比较”,用来比较属性和值以判定是否需要更新组件。这种模式十分常见,因此React提供了一个辅助对象来实现这个逻辑 - 继承自React.PureComponent
。以下代码可以更简单的实现相同的操作:
class CounterButton extends React.PureComponent { constructor(props) { super(props); this.state = {count: 1}; } render() { return ( ); } }
PureComponent
原理
当组件更新时,如果组件的 props 和 state 都没发生改变, render 方法就不会触发,省去 Virtual DOM 的生成和比对过程,达到提升性能的目的。具体就是 React 自动帮我们做了一层浅比较:
if (this._compositeType === CompositeTypes.PureClass) { shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState); }
而 shallowEqual 又做了什么呢?会比较 Object.keys(state | props) 的长度是否一致,每一个 key 是否两者都有,并且是否是一个引用,也就是只比较了第一层的值,确实很浅,所以深层的嵌套数据是对比不出来的。
问题
大部分情况下,你可以使用React.PureComponent而不必写你自己的shouldComponentUpdate,它只做一个浅比较。但是由于浅比较会忽略属性或状态突变的情况,此时你不能使用它。
class ListOfWords extends React.PureComponent { render() { return{this.props.words.join(',')}; } } class WordAdder extends React.Component { constructor(props) { super(props); this.state = { words: ['marklar'] }; this.handleClick = this.handleClick.bind(this); } handleClick() { // This section is bad style and causes a bug const words = this.state.words; words.push('marklar'); this.setState({words: words}); } render() { return (); } }
在ListOfWords中,this.props.words是WordAdder中传入的其state的一个引用。虽然在WordAdder的handelClick方法中被改变了,但是对于ListOfWords来说,其引用是不变的,从而导致并没有被更新。
解决方法
在上面的问题中可以发现,当一个数据是不变数据时,可以使用一个引用。但是对于一个易变数据来说,不能使用引用的方式给到PureComponent。简单来说,就是我们在PureComponent外层来修改其使用的数据时,应该给其赋值一个新的对象或者引用,从而才能确保其能够进行重新渲染。例如上面例子中的handleClick可以通过以下几种来进行修改从而确认正确的渲染:
handleClick() { this.setState(prevState => ({ words: prevState.words.concat(['marklar']) })); }
或者
handleClick() { this.setState(prevState => ({ words: [...prevState.words, 'marklar'], })); };
或者针对对象结构:
function updateColorMap(oldObj) { return Object.assign({}, oldObj, {key: new value}); }
immutable.js
Immutable.js是解决这个问题的另一种方法。它通过结构共享提供不可突变的,持久的集合:
不可突变:一旦创建,集合就不能在另一个时间点改变。
持久性:可以使用原始集合和一个突变来创建新的集合。原始集合在新集合创建后仍然可用。
结构共享:新集合尽可能多的使用原始集合的结构来创建,以便将复制操作降至最少从而提升性能。
// 常见的js处理 const x = { foo: 'bar' }; const y = x; y.foo = 'baz'; x === y; // true // 使用 immutable.js const SomeRecord = Immutable.Record({ foo: null }); const x = new SomeRecord({ foo: 'bar' }); const y = x.set('foo', 'baz'); x === y; // false
看完上述内容,你们掌握PureComponent如何在React中使用的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注创新互联行业资讯频道,感谢各位的阅读!
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流