【React】什么时候使用shouldComponentUpdate方法?
2017-08-01 14:11
609 查看
你听说React是一个很快的前端框架,决定试一试。然后你找了个样例开始了React之旅,这时你注意到
答案是React确实很快…不过是在某些时候。其他时候,你应该使用shouldComponentUpdate,但是其他时候是什么时候呢?如果只是一个是或否的问题,你可能会问确定是否使用
如果不能,那就别用。
如果它没用,React也不会有这样一个紧急的性能出口。当你使用它时,问自己是否需要?总之,你可能偶尔还是要用到的。
我们来看看背后的原理,从这里开始吧:
添加
是的,你没看错,一个保证性能的出口的确能拖慢组件的性能。如何做到的呢?回答这个问题,我们需要先问什么是React?
React非常聪明的实现了
但是,React做的不仅仅是算出是否该更新组件。还需要确定如何去更新它。
React是如何确定什么时候去渲染组件的呢?
这是一个好问题!所以你了解你为每个组件写的渲染方法吗?它看起像返回了一段类似Html的jsx代码(或者你用Raw React会返回ReactElement对象),但是你会惊讶的听到渲染方法返回的是一个普通的js对象。看起来是这样的:
当然,它可能会被装饰成
或者用其他方式渲染,如果我们伪装
我们知道
如果
但是你会说有种情况是
使用
所以当你渲染一个很大的table,你从props中提取数据,调用render方法来计算,然后通过Immutable.js 来判断数据是否相等。
在上面的场景中,
小于1毫秒的10倍仍然小于1毫秒。
Donald Knuth 曾经写过:“过早的优化是一切的万恶之源”。
原因是这样的,
维护
但是如果
什么时候使用
一旦
希望上一节已经说服你,
什么是分析器?它就是我之前提到的尺子。一个好的分析器可以让你测量你所有的程序。它可以得到你每个方法运行的时间。
通过比较render方法在添加
你只需要进入 the project按步骤来完成练习.
开始之前,你需要知道如何打开浏览器的分析器。你可以在这里了解到:Chrome 或者 Firefox
打开js分析器
开始记录
点击 “Toggle synergy!” 让页面循环5秒
点击你开始记录的按钮来停止记录
在列表的最上面部分找到render方法,记录所花的时间,
如果render所花的时间足够的少,没有出现在时间花费列表前面,恭喜你!你不用使用
当你加了
组件中写了
上面的方法不一定准确,实际的结果可能相差很大。如果你不相信我,你可以尝试上面的步骤来试试。如果结果不准确,那么怎么抉择呢?
讲真的,这种方法得出的结果相差很大,这种方法只可以给你提供一个粗略的测算。(请不要把这个方法给统计学家看)
如果没加
正确的写
现在我摇着你的手告诉你用“Immutable.js”就可以了,此时我猜你的内心os应该这样的:
Immutable.js不是完美的解决方案,也不是唯一的,ES6的Object.assign也可以达到差不多的效果
如果不可变的状态不能解决你的问题,那什么才可以呢?
我很高兴你这么问!正真的解决方案是良好的状态结构。事实上,好的状态结构将解决你
原文链接:http://jamesknelson.com/should-i-use-shouldcomponentupdate/
shouldComponentUpdate和
PureRenderMixin,通过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的代码很难。比如加一个新的prop到render方法,但是忘了更新
shouldComponentUpdate?这就是一个bug。最糟糕的是这些bugs在测试中不会出现,有可能是你第一次给客户展示的时候出现。
但是如果
shouldComponentUpdate真的容易引起很多bug,它显然需要一些使用定律,所以问题就变成了…
什么时候使用shouldComponentUpdate
一旦shouldComponentUpdate给你带来了可感知的性能提升,就使用它。
希望上一节已经说服你,
shouldcomponentupdate有一些缺陷。带着这个想法,当你确定要使用它时,你需要一把尺子,是一个非常花哨的技术。
测量性能提升
这里有个 方法 你可以测量shouldComponentUpdate带来的提升, 下面我将集中讨论JavaScript分析器.
什么是分析器?它就是我之前提到的尺子。一个好的分析器可以让你测量你所有的程序。它可以得到你每个方法运行的时间。
通过比较render方法在添加
shouldComponentUpdate之前和之后花费的时间,我们能得到性能提升的数值。当然,我们也将需要考虑
shouldComponentUpdate所花费的时间 - 它不是免费使用的。最后得出性能的提升比起维护成本是否是值得的。
练习
我把演示例子放到了 fiddle(https://jsfiddle.net/nsh4b3Ly/2/)上. Enterprise组件为了满足需求,将使用shouldComponentUpdate; 然后对原始数据进行处理, 使得它频繁的触发渲染方法, 其次是它的 props 包含不可变数据.
你只需要进入 the project按步骤来完成练习.
开始之前,你需要知道如何打开浏览器的分析器。你可以在这里了解到:Chrome 或者 Firefox
第一步: 测试不加shouldComponentUpdate的版本
当触发点击的时候,我们来测量渲染的时间:打开js分析器
开始记录
点击 “Toggle synergy!” 让页面循环5秒
点击你开始记录的按钮来停止记录
在列表的最上面部分找到render方法,记录所花的时间,
如果render所花的时间足够的少,没有出现在时间花费列表前面,恭喜你!你不用使用
shouldComponentUpdate。或者说你在解决其他性能问题前你不必考虑它。
第二步: 测试加了shouldComponentUpdate的版本
这一步,我们加了shouldComponentUpdate到App组件,来测试渲染时间。
shouldComponentUpdate方法,代码已经为你准备好了:
shouldComponentUpdate(nextProps, nextState) { return !Immutable.is(this.state.synergy, nextState.synergy) },
当你加了
shouldComponentUpdate,重复第一步的步骤,以下是结果:
组件中写了
shouldComponentUpdate的render:
shouldComponentUpdate:
上面的方法不一定准确,实际的结果可能相差很大。如果你不相信我,你可以尝试上面的步骤来试试。如果结果不准确,那么怎么抉择呢?
讲真的,这种方法得出的结果相差很大,这种方法只可以给你提供一个粗略的测算。(请不要把这个方法给统计学家看)
抉择
从我的经验来看,如果添加shouldComponentUpdate方法,可以节约一半的渲染时间,那么它是对你有利的。
如果没加
shouldComponentUpdate之前的渲染只花了100ms,那就没有必要用
shouldComponentUpdate了。
正确的写 shouldComponentUpdate
方法
现在我摇着你的手告诉你用“Immutable.js”就可以了,此时我猜你的内心os应该这样的:Immutable.js不是完美的解决方案,也不是唯一的,ES6的Object.assign也可以达到差不多的效果
如果不可变的状态不能解决你的问题,那什么才可以呢?
我很高兴你这么问!正真的解决方案是良好的状态结构。事实上,好的状态结构将解决你
shouldComponentUpdate部署问题;它解决了你所有问题。
原文链接:http://jamesknelson.com/should-i-use-shouldcomponentupdate/
相关文章推荐
- 在Vue2.0 使用v-for时报这样的错误:component lists rendered with v-for should have explicit keys.解决方法:
- react中的shouldComponentUpdate
- React高级教程(es6)——(4)ShouldComponentUpdate的用法
- react与mox-react的shouldComponentUpdate 理解
- react-bits:shouldComponentUpdate() check
- reactjs性能优化之shouldComponentUpdate
- AJAX中关于多个UpdatePanel 的 UpdateProgress 的使用方法
- 自定义控件在AJAX的UpdatePanel中使用时添加javascript脚本方法
- asp:UpdatePanel 中 GridView 使用 LinkButton 选择无反应 解决方法
- 使用Sharepoint的Lists Web Service调用UpdateListItems方法"增/删/改"List Items
- UpdatePanel的使用方法
- Debian 中使用apt-get update 出现NO_PUBKEY 解决方法
- saveOrupdate方法如何使用 (转帖网址:http://www.javaeye.com/topic/2632)
- weblogic81下使用hibernate3的update query方法应注意的问题
- Ajax(5)UpdatePanel的使用方法
- updatepanel中不能使用fileupload的弥补方法
- 关于使用updatepanle后页面还会刷新的个人解决方法。
- 在asp中使用js的encodeURIComponent方法
- 注解的力量 -----Spring 2.5 JPA hibernate 使用方法的点滴整理(五):使用@Component 来简化bean的配置
- Ajax(5)UpdatePanel的使用方法