react效率

432 阅读2分钟

为了提升效率努力让努力变的更纯(pure),减少在组件更新周期的重新渲染;

  1. 使用react-addons-pure-render-mixin或React.PureComponent可以让组件自行判断props(浅层)的变化;帮助我们实现shouldComponentUpdate的控制,减少其他非组件相关数据变化引起的重新渲染;

  2. 使用了以上内容之后需注意:

(1)直接为 props 设置对象或数组等字面量形式:

如:   <Item style={{ color: 'black' }} /> 


因为每次调用 React 组件其实都会重新创建组件。就算传入的数组或对象的值没有改变,它们引用的地址也会发生改变。

解决方法:在外部定义完变量再引用:const defaultStyle = {}; 尽量使用const;

(2),不能在组件上绑定事件时不能使用以下两种形式:

第一种绑定是因为每次调用时会重新bind(this),导致方法的引用每次都会改变;第二种是每次都会重新生成箭头函数,导致引用改变。

解决方法:在construct里绑定this;

(3),子组件里有子组件:

 render() { 
     return ( 
     <Item> 
         <span>Arcthur</span> 
     <Item/> 
     ) 
   } 
 } 

上面的子组件 JSX 部分翻译过来,其实是:

    <Item 
     children={React.createElement('span', {}, 'Arcthur')} 
    /> 

解决方法:子组件设置 PureRender;
  1. 尽量使用具体的prop,不使用{...props}等形式;

  2. map里面添加key,并且key不要使用index(可变的),尽量使用id等判断。

  3. 使用 Immutable 进一步提升组件的渲染性能 :

     (1),为了保存原状态(刷新或对比时使用)很多时候都会用到浅拷贝或者深拷贝,这个时候会造成 CPU 和内存的浪费,这个时候可以使用Immutable 定义数据,修改数据时不会改变原数据(注意接收返回的新数据),同时Immutable 使用了结构共享(structural sharing),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其他节点则进行共享,所以也不会引起新的效率问题。
    
     (2),使用PureRender时:以上介绍了PureRender官方提供的形式,而Immutable.js 则提供了简洁、高效的判断数据是否变化的方法,只需 === 和 is 比较就能知道是否需要执行 render,而这个操作几乎零成本,所以可以极大提高性能。使用Immutable 级可以更深入的实现,如下:
    
    import { is } from 'immutable'; 
        shouldComponentUpdate(nextProps, nextState) {
          const thisProps = this.props || {};
          const thisState = this.state || {};
          if (Object.keys(thisProps).length !== Object.keys(nextProps).length ||
            Object.keys(thisState).length !== Object.keys(nextState).length) {
            return true;
          }
          for (const key in nextProps) {
            if (nextProps.hasOwnProperty(key) &&
              !is(thisProps[key], nextProps[key])) {
              return true;
            }
          }
          for (const key in nextState) {
            if (nextState.hasOwnProperty(key) &&
              !is(thisState[key], nextState[key])) {
              return true;
            }
          }
          return false;
        }