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

不得不吐槽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"])
  );
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值