前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >什么时候该适用shouldComponentUpdate

什么时候该适用shouldComponentUpdate

原创
作者头像
用户2303251
修改2018-06-07 17:00:53
7310
修改2018-06-07 17:00:53
举报
文章被收录于专栏:田云专栏田云专栏田云专栏

http://jamesknelson.com/should-i-use-shouldcomponentupdate/

James K Nelson最近发表了一篇文章,标题是《Should I use shouldComponentUpdate?》。他在这篇文章中介绍了应该在什么情况下使用React组件中的shouldComponentUpdate方法。

接触过React的人应该都知道它是一个非常快的前端框架,或许也听说过shouldComponentUpdate可以让它更快。但你知不知道它们在什么情况下才能发挥作用?也就是说,你知道什么时候需要动手写shouldComponentUpdate方法吗?

James指出,如果你在React组件中写了shouldComponentUpdate方法后不能获得可测量的,并且是可察觉到的性能提升,那就不要写

你的意思是我不应该用它

按照React团队的说法,shouldComponentUpdate是保证性能的紧急出口,既然是紧急出口,那就意味着我们轻易用不到它。但既然有这样一个紧急出口,那说明有时候它还是很有必要的。所以我们要搞清楚到底什么时候才需要使用这个紧急出口。

为了讲清楚这个问题,James对React的渲染机制做了深入地剖析。

他首先指出:

  添加shouldComponentUpdate方法一般都会拖慢组件的更新速度。
 

为什么会这样呢?因为在他看来,React基本上就是一个非常聪明的shouldComponentUpdate实现。它不仅知道应该在什么时候更新组件,还知道应该如何更新组件,并且这两件事情它都做得很好。那么React是如何知道是否应该更新组件的呢?这要从组件中的render方法说起。

尽管在写代码时,我们看到render返回的都是JSX或者ReactElement,但实际上,它返回的都是下面这种普通的JavaScript对象:

{
  type: 'ul',
  props: { className: 'what-do-you-want-to-do-tonight' },
  children: [{ 
    type: 'li', 
    children: 'The same thing we do every night, pinky.' 
  },]
}
 

React就是用这种对象来描述要在界面中渲染的标签。如果跟上次渲染时所用的对象比较,数据没有发生变化,显然就不用更新界面中的DOM。

换句话说,React已经替我们实现了一个shouldComponentUpdate。为了简化,我们可以假装props不是绑在组件的this上的,而是直接传给了render,那么React的实现基本上就是下面这样的:

shouldComponentUpdate(nextProps) {
  return !deepEquals(render(this.props), render(nextProps))
}

你是知道的,对于比较小的对象来说,deepEquals很快,但如果是个层层嵌套的大家伙,它的速度就不行了。因此我们可以得出第一条结论:

如果render的返回值很小,但props是个大家伙,那自己写shouldComponentUpdate很可能不会带来什么好结果。

那这是不是说,如果render返回的值足够大,我们自己写shouldComponentUpdate就会比较划算呢?实际上也不尽然。

讲到这里,James又给出了他观察到的第二个事实:

使用shouldComponentUpdate得到的收益一般是微乎其微的。

他举了一个例子:比如要渲染一个table,我们从props中得到数据,然后又对这些数据做了些计算。并且这些数据都是放在Immutable.js的结构中的,因此通过比较引用是否相等就能判断出props是否发生了变化。

在这样一个场景中,如果我们自己写shouldComponentUpdate,那速度要比React默认实现的处理速度快很多。James说他观察到的结果是最少快十倍!对,你没看错,他确实是这样说的,但他紧接着又说:

不足一毫秒的渲染时间在速度提升了10倍之后,依然也还是不足一毫秒。

React团队说shouldComponentUpdate是个紧急出口,而不是加速按钮应该就是出于这个原因。但James给出了一个更形象的比喻,他说用shouldComponentUpdate就是没有采取安全措施的性行为。

因为他觉得有时候很有必要写shouldComponentUpdate,并且那些时候shouldComponentUpdate肯定会让你的app有更好的表现。但是这也是导致bug的主要原因之一,并且还都是一些不太容易察觉的bug。接着他又给出了几个具体的例子,并指出这些bug在测试中很难发现。如果在给客户演示的时候跳出来,那后果就不堪设想了。

什么时候需要写shouldComponentUpdate?

因此还是回到了最初的那个问题上,什么时候需要自己动手写shouldComponentUpdate方法?他再次重申了前文中给出的那个答案:

只有经过测量,发现有了shouldComponentUpdate后组件的渲染速度确实有可察觉的提升,你才应该用它。

那什么才算是好得不容置疑的结果呢?按照James的经验,如果加上shouldComponentUpdate之后渲染时间减少了一半,那用shouldComponentUpdate应该是真的对你有好处的。但同时也不要忘记,只有原来的渲染时间足够长时,这种性能上的提升才是有意义的。假如本来只用了100ms,那你折腾半天加快的那点速度人们依然是感觉不到的。

所以在最终要做决定的时候,你要记住使用shouldComponentUpdate会带来维护上的挑战;并且测量结果是不准确的;而且性能改善的幅度还要是能感觉到的那种,只有记住这三点,你才能做出正确的决定。当然,这一切的前提是你的shouldComponentUpdate实现是没有问题的。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 你的意思是我不应该用它
  • 什么时候需要写shouldComponentUpdate?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档