React应用性能优化之shouldComponentUpdate与key
虽然React 的 vDom diff算法能保证最小程度的 DOM 改变,但当组件树嵌套得非常深时,就不得不需要渲染一个新的虚拟 DOM 来让应用运行得更加高效。
shouldComponentUpdate
设置新 props,调用 setState 方法或 forceUpdate 方法时,React 都会调用该组件所有子组件的 render 方法。但是在组件树深度嵌套或 render 方法十分复杂的时侯,页面就会有延迟。
但此时,某些子组件并没有必要更新,或者永远都不需要更新,这时进行的计算过程是没有必要的。
而 shouldComponentUpdate 方法正是用来判断是否需要调用指定组件的 render 方法。
shouldComponentUpdate 方法返回一个布尔值。false 表示不要调用 render 方法;true 表示需要调用 render 方法计算出新的虚拟 DOM。
此方法的默认值是 true。 并且,组件首次渲染时,shouldComponentUpdate 方法不会被调用
shouldComponentUpdate 方法接受两个参数,新的 props 和新的 state:
React.creatClass({
shouldComponentUpdate: function (nextProps, nextState) {
return nextProps.id !== this.props.id
}
})
另外,我们也可以添加 React.addons.PureRenderMixin 插件来处理 shouldComponentUpdate。 这个插件会重写 shouldComponentUpdate 方法,并在该方法内对新老 props 及 state 进行对比, 如果发现它们完全一致则返回 false, 就像上面的例子一样。官方文档里也有介绍: PureRenderMixin
import PureRenderMixin from 'react-addons-pure-render-mixin';
class FooComponent extends React.Component {
constructor(props) {
super(props);
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
}
render() {
return foo;
}
}
key(键)
在遍历列表的时候,没有组件添加 key 值会有 warnning 产生。那它是用来干嘛的呢? 假设有一个 div 组件,它的 key 属性为 ‘foo’,之后又改为 ‘bar’, 那 React 就会跳过 DOM diff, 同时完会弃置 div 所有的子元素,并重新渲染。除了告诉 React 什么时候要抛弃一个节点之外,key 还可以在元素顺序改变时使用。
render: function(){
return items.map(function(item){
return item.name
})
}
如果像上面这样,React 在li 列表顺序改变的时候就不会重新渲染,而是采用 insertBefore 操作,这也是最高效的方法。
但是要注意,key 值必须是独一无二的,最好不要是数字,绝对不能是遍历中的index。这样可以保证从一个父组件移动到另一个父组件的情况是不会被处理的。
key 值也是无法读取的。