antd mobile(十) 性能优化PureRender的使用

来源:互联网 发布:遗传算法python实现 编辑:程序博客网 时间:2024/06/07 22:36

不得不吐槽react,确实不是新手玩的东西,一句话就是水深坑多啊。如果是前台新手我还是不建议直接使用这种框架开发。

搜索react的性能优化,都提到了用pureRender来优化其性能,其实就是减少虚拟dom跟实际dom的diff的计算。但在dva这种架子下面,根本没法使用pureRender来进行性能优化,因为返回的永远是true,根本就做不到减少渲染的效果。

分析下了pureRender源代码,将props和nextProps打印出来看看。

    console.log(this.props);    console.log(nextProps);    //这里shallowEqual是react-addons-pure-render-mixin提供的对象浅对比方法    console.log(!shallowEqual(this.props, nextProps));

只要通过了reducer进行了值的变更,如果只是简单的用眼观察,会发现this.props跟nextProps是一样的,但是通过shollowEqual则返回的却是false,跟踪代码会发现问题出现在this.props跟nextProps里面的reducer对象不是同一个对象造成的。

function is(x, y) {     if (x === y) {        console.log("-----------是同一对象----")        console.log(x);        // Steps 1-5, 7-10        // Steps 6.b-6.e: +0 != -0        // Added the nonzero y check to make Flow happy, but it is redundant        return x !== 0 || y !== 0 || 1 / x === 1 / y;      } else {        console.log("-----------不是同一对象----")        console.log(x);        // Step 6.a: NaN == NaN        return x !== x && y !== y;      }}

比如我界面注册了singlePlanMd的reducer对象

export default connect((singlePlanMd) => ({singlePlanMd}))(SinglePlan)

这时候只要通过dispatch对参数进行过修改,会发现is(this.props.singlePlanMd.singlePlanMd, nextProps.singlePlanMd.singlePlanMd)就是false咯。
再对该值取反,则永远是true 也就是每次都会render

  shouldComponentUpdate(nextProps, nextState) {     return !is(this.props.singlePlanMd.singlePlanMd, nextProps.singlePlanMd.singlePlanMd)  }

按理来说这样是没问题的因为每次修改就是希望重新渲染界面,但在有些场合并不希望如此操作。

    dispatch({      type: 'singlePlanMd/setCurAnimate',      curAnimate: 'left',      scroll: {        taskList: 0      }    });

比如现在有这么个需求,就是界面滚动后,界面的滚动位置保存到全局的Md里面,然后跳转界面后,再回到当前界面时,读取对应的滚动参数,并将界面滚动指定位置。
这时候如果每次记录滚动位置都render自然就太费性能咯,这种存储参数值的应该不触发更新操作,才比较合理。

为了实现该效果,为了提高性能所以项目组约定如果是nextProps与this.props的属性长度不一样时触发刷新,如果是nextProps与this.props的第一层属性是常规属性而且值不一样时才刷新,如果第一层属性是对象则判断该对象的属性长度是否一致,如果一致则不需要刷新,如果不一致则刷新,而不对值的变化进行监听。

比如在this.props里面设置一个scroll对象,如果对scroll对象的值进行变更则不会触发刷新功能。
这是封装后的组件更新代码如下:

  shouldComponentUpdate(nextProps, nextState) {    return goingComponentUpdate(this, nextProps, nextState,"singlePlanMd");  }

goingComponentUpdate的代码大概如下:

function shallowEqual(objA, objB) {  if (is(objA, objB)) {    return true;  }  if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {    return false;  }  var keysA = Object.keys(objA);  var keysB = Object.keys(objB);  if (keysA.length !== keysB.length) {    return false;  }  // Test for A's keys different from B.  for (var i = 0; i < keysA.length; i++) {    if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {      return false;    }  }  return true;}export function goingComponentUpdate(pageObj,nextProps, nextState,mdName) {  return (    !shallowEqual(pageObj.props, nextProps) || !shallowEqual(pageObj.state, nextState)||    !shallowEqual(pageObj.props[mdName][mdName], nextProps[mdName][mdName]) ||!shallowEqual(pageObj.props[mdName]["AppMd"], nextProps[mdName]["AppMd"])  );}