最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 使用 shouldComponentUpdate方法? [React]

    正文概述 掘金(众成翻译)   2021-01-05   628

    译者:miaoYu

    原文链接

    你听说React是一个很快的前端框架,决定试一试。然后你找了个样例开始了React之旅,这时你注意到shouldComponentUpdatePureRenderMixin,通过google找到一些技巧让React变得更快。但是React真的快吗?

    答案是React确实很快...不过是在某些时候。其他时候,你应该使用shouldComponentUpdate,但是其他时候是什么时候呢?如果只是一个是或否的问题,你可能会问确定是否使用shouldComponentUpdate,会那么容易吗?你可能不信,但它就是那么容易。

    shouldComponentUpdate将带来可测量和可感知的提升?

    如果不能,那就别用。

    那你的意思是我可能不会用它?

    你可能应该避免用它。据React团队的说法,shouldComponentUpdate是一个保证性能的紧急出口,意思就是你不到万不得已就别用它。当然这也不是绝对。

    如果它没用,React也不会有这样一个紧急的性能出口。当你使用它时,问自己是否需要?总之,你可能偶尔还是要用到的。

    我们来看看背后的原理,从这里开始吧:

    添加shouldComponentUpdate方法将拖慢你组件的性能。

    是的,你没看错,一个保证性能的出口的确能拖慢组件的性能。如何做到的呢?回答这个问题,我们需要先问什么是React?

    React非常聪明的实现了shouldComponentUpdate

    但是,React做的不仅仅是算出是否该更新组件。还需要确定如何去更新它。

    React是如何确定什么时候去渲染组件的呢?

    这是一个好问题!所以你了解你为每个组件写的渲染方法吗?它看起像返回了一段类似Html的jsx代码(或者你用Raw React会返回ReactElement对象),但是你会惊讶的听到渲染方法返回的是一个普通的js对象。看起来是这样的:

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

    当然,它可能会被装饰成JSX或者 冒充成React.createElement,但是正确形式的render()的输出是一个你标记的对象。如果那个对象在预渲染中发现没有改变,那么它将不会被渲染到DOM上。

    或者用其他方式渲染,如果我们伪装render方法接受props来取代直接触发render方法,那么代码看起来是这样的:

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

    我们知道deepEquals对于简单对象处理是很快的,但是对于嵌套很深的对象处理很慢,所以这个近似值给我们一个很好的法则:

    如果render方法返回的对象很小,但是props对象很大,那么shouldComponentUpdate将对性能带来很大的拖累。

    但是你会说有种情况是render方法返回的值足够大以至于你可以通过 shouldComponentUpdate 获得某些东西?

    使用shouldComponentUpdate的收获通常是无关紧要的

    所以当你渲染一个很大的table,你从props中提取数据,调用render方法来计算,然后通过Immutable.js 来判断数据是否相等。

    在上面的场景中,shouldComponentUpdate比起React默认的处理方式带来了巨大的性能提升。事实上,以我的经验来看,至少10倍。但是在这个场景中,如何收获微不足道?答案是肯定的。

    小于1毫秒的10倍仍然小于1毫秒。

    Donald Knuth 曾经写过:“过早的优化是一切的万恶之源”。

    维护shouldComponentUpdate很困难

    所以如果我不得不猜测,React团队把shouldComponentUpdate叫做紧急出口,而不是叫性能按钮的原因就是维护困难,但是老实说,我认为紧急出口这个叫法不合适。shouldComponentUpdate应该更像是无保护的性行为。

    原因是这样的,shouldComponentUpdate有时候是必要的,它能让你的应用性能更好。但是它也能引起巨大的bugs,而且不容易被发现。

    维护shouldComponentUpdate的代码很难。比如加一个新的proprender方法,但是忘了更新shouldComponentUpdate?这就是一个bug。最糟糕的是这些bugs在测试中不会出现,有可能是你第一次给客户展示的时候出现。

    但是如果shouldComponentUpdate真的容易引起很多bug,它显然需要一些使用定律,所以问题就变成了...

    什么时候使用shouldComponentUpdate

    一旦shouldComponentUpdate给你带来了可感知的性能提升,就使用它。

    希望上一节已经说服你, shouldcomponentupdate有一些缺陷。带着这个想法,当你确定要使用它时,你需要一把尺子,是一个非常花哨的技术。

    测量性能提升

    这里有个 方法   你可以测量 shouldComponentUpdate带来的提升, 下面我将集中讨论JavaScript分析器.

    什么是分析器?它就是我之前提到的尺子。一个好的分析器可以让你测量你所有的程序。它可以得到你每个方法运行的时间。

    使用 shouldComponentUpdate方法? [React]

    通过比较render方法在添加shouldComponentUpdate之前和之后花费的时间,我们能得到性能提升的数值。当然,我们也将需要考虑shouldComponentUpdate所花费的时间 - 它不是免费使用的。最后得出性能的提升比起维护成本是否是值得的。

    很简单对吧?不要相信我的话哈,我们用一个例子来演示一下。通过订阅我的消息可以免费获取一个高性能的react组件。

    Get the PDF cheatsheet!

    PDF组件

    <input type=""text"" name=""first_name"" placeholder=""First name"" id=""ck_firstNameField"" required="""">

    <input type=""email"" name=""email"" placeholder=""Email address"" id=""ck_emailField"" required="""">

    <button id=""ck_subscribe_button"">订阅我

    练习

    我把演示例子放到了 fiddle上. Enterprise组件为了满足需求,将使用shouldComponentUpdate; 然后对原始数据进行处理, 使得它频繁的触发渲染方法, 其次是它的 props 包含不可变数据.

    你只需要进入 the project按步骤来完成练习.

    开始之前,你需要知道如何打开浏览器的分析器。你可以在这里了解到:Chrome 或者 Firefox

    第一步: 测试不加shouldComponentUpdate的版本

    当触发点击的时候,我们来测量渲染的时间:

    1. 打开js分析器

    2. 开始记录使用 shouldComponentUpdate方法? [React]

    3. 点击 “Toggle synergy!” 让页面循环5秒使用 shouldComponentUpdate方法? [React]

    4. 点击你开始记录的按钮来停止记录

    5. 在列表的最上面部分找到render方法,记录所花的时间,使用 shouldComponentUpdate方法? [React]

    如果render所花的时间足够的少,没有出现在时间花费列表前面,恭喜你!你不用使用shouldComponentUpdate。或者说你在解决其他性能问题前你不必考虑它。

    第二步: 测试加了shouldComponentUpdate的版本

    这一步,我们加了shouldComponentUpdateApp组件,来测试渲染时间。shouldComponentUpdate方法,代码已经为你准备好了:

    `shouldComponentUpdate(nextProps, nextState)  {  return  !Immutable.is(this.state.synergy, nextState.synergy)  },`
    

    当你加了shouldComponentUpdate,重复第一步的步骤,以下是结果:

    组件中写了shouldComponentUpdaterender:

    使用 shouldComponentUpdate方法? [React]

    shouldComponentUpdate:

    使用 shouldComponentUpdate方法? [React]

    上面的方法不一定准确,实际的结果可能相差很大。如果你不相信我,你可以尝试上面的步骤来试试。如果结果不准确,那么怎么抉择呢?

    讲真的,这种方法得出的结果相差很大,这种方法只可以给你提供一个粗略的测算。(请不要把这个方法给统计学家看)

    抉择

    从我的经验来看,如果添加shouldComponentUpdate方法,可以节约一半的渲染时间,那么它是对你有利的。

    如果没加shouldComponentUpdate之前的渲染只花了100ms,那就没有必要用shouldComponentUpdate了。

    正确的写 shouldComponentUpdate方法

    现在我摇着你的手告诉你用“Immutable.js”就可以了,此时我猜你的内心os应该这样的:

    使用 shouldComponentUpdate方法? [React]

    Immutable.js不是完美的解决方案,也不是唯一的,ES6的Object.assign也可以达到差不多的效果

    如果不可变的状态不能解决你的问题,那什么才可以呢?

    我很高兴你这么问!正真的解决方案是良好的状态结构。事实上,好的状态结构将解决你 shouldComponentUpdate部署问题;它解决了你所有问题。

    怎样构造好的状态呢?我将在这个帖子上回答 - Luddite’s guide to Redux State(快完成了),不想错过的话?订阅我消息!

    使用 shouldComponentUpdate方法? [React]

    最后,我想看到你的问题、建议和意见,如果你有什么想说的,发邮件给我james@jamesknelson.com,我期待你的来信。

    扩展阅读

    • Learn Raw React — no JSX, Flux, ES6, Webpack…

    • Object.assign at MDN


    起源地下载网 » 使用 shouldComponentUpdate方法? [React]

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元