React Fiber的实现原理怎么理解,能够做什么
Admin 2022-06-24 群英技术资讯 434 次浏览
React Fiber,简单来说就是一个从React v16开始引入的新协调引擎,用来实现Virtual DOM的增量渲染。
说人话:就是一种能让React视图更新过程变得更加流畅顺滑的处理手法。
我们都知道:进程大,线程小。而Fiber(纤维)是一种比线程还要细粒度的处理机制。从这个单词也可以猜测:React Fiber会很“细”。到底怎么个细法,我们接着往下看。
之前说了,React Fiber是为了让React的视图更新过程变得更加流畅顺滑。怎么,之前React的视图更新不流畅,不顺滑了?
还真是的,在React v16之前,React的视图更新确实存在很大的性能问题,其中首当其冲的,就是它的同步更新机制。
在React决定要加载或更新一颗组件树之前,会大致做出如下一系列动作:调用各组件的生命周期函数 --> 计算和对比Virtual DOM --> 更新真实的DOM树。这个过程是同步的,也就是说,一旦这个过程开始,它就会一鼓作气跑完,一直到真实DOM树更新完毕。
然而,当组件树比较庞大时,这种机制的问题就来了:一颗拥有300个组件的组件树需要全部更新,假设一个组件更新只需耗时1ms,整棵树更新一次就需要耗时300ms。在这300ms期间,浏览器的主线程一直在“专心致志”地忙着更新这颗组件树(这时函数的调用栈会非常长),对于页面上的任何操作都是“不闻不问”的。在这期间,假如用户在一个输入框敲了几个字,页面上也不会有任何反应,因为渲染按键输入结果也需要主线程来做,然而此时主线程正忙着更新组件树呢。等到300ms结束了,浏览器主线程有空了,才把刚刚敲的那几个字渲染到input输入框内。
太卡了,真的。
由于JavaScript的单线程工作特点,业内一直有个这样的原则:任何动作都不要长时间霸占主线程,如果迟迟不归还主线程,那么在这期间程序就没法对其他输入作出响应。输入了却没有响应,或者说响应来的很慢,也就是我们常常说的“卡顿”。显然,React的同步更新机制在组件树庞大时就违反了这一原则,犯了大忌。
这就是React Fiber出现的原因:为了解决旧版React视图更新的性能瓶颈。
首先,React Fiber并没有解决更新庞大组件树耗时长的问题,实际上总的耗时还是一样的长。但是它解决了一个被广大开发者口诛笔伐的恶行:长时间霸占主线程不放。
而它解决的方法就是:分片。
它的工作原理是这样的:把耗时长的更新任务拆解成一个个小的任务分片,每执行完一个小的任务分片,都归还一次主线程,看看有没有什么其他紧急任务要做。如果在归还主线程时恰巧发现有紧急任务,那么会马上停掉当前更新任务,转而让主线程去做紧急任务,等主线程做完紧急任务,再重新做更新任务。(注意️:是重新!不是从上次被打断的点继续);如果没有紧急任务,才敢唯唯诺诺地继续做接下来的任务分片。
简单来说,就是降了视图更新的优先级,把更新过程碎片化。
现在我们捋一捋,React Fiber会这样处理一个更新过程:
React Fiber实现的难点有两个:暂停/重启如何实现?任务如何分散执行?
对于前者,暂停/重启意味着我们需要保存状态,这里在实现上用到了具有链表和指针的“单链表树遍历算法”,能够记录遍历过程中的上一步和下一步。
而对于后者,则用到了requestAnimationFrame
和requestIdelCallback
这两个API,其中requestAnimationFrame
是浏览器在每一帧都一定会执行的,可以放一些高优先级的任务;而requestIdelCallback
则是浏览器在一帧中最后如果有空闲时间才会去执行,可以放一些低优先级的任务,需要polyfill(因为兼容性不佳)。
React Fiber在Reconciliation阶段可能会调用以下生命周期函数(这也意味着在这个阶段的生命周期函数在一次加载和更新过程中可能会被多次调用):
componentWillMount
componentWillUpdate
componentWillReceiveProps
shouldComponentUpdate
如果你恰巧没有上react hooks的车,而是使用传统的类组件进行开发,那么切记,不要在以上几个生命周期函数中做只需要做一次的操作(比如:页面初始化时发起一个ajax请求获取数据)。
如果你平常使用react hooks进行开发,那没事了,就当看了个热闹。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
本文给大家分享的是window下自带name的属性的内容,一些朋友可能对于window的name属性的作用和使用等等,不是很了解,对此这本文就简单的介绍一下,接下来我们一起了解看看吧。
对象有两种属性,普通的数据属性和访问器属性。访问器属性本质上是用于获取和设置值的函数(可以拦截、过滤、处理等操作要设置或获取的属性),但从外部代码来看就像传统属性一样。
Nodejs中怎么操作文件?下面本篇文章带大家聊聊怎么使用Nodejs读写文件,希望对大家有所帮助!
这篇文章给大家分享的是有关vue登录图形验证码的内容,图像验证码在很多登录页面都会使用到,小编觉得挺实用的,因此分享给大家做个参考,接下来一起跟随小编看看吧。
jquery修改某一行值的方法:1、利用eq()方法获取指定行元素对象,语法为“元素对象.eq(行元素的索引)”;2、利用html()方法来修改已获取到指定行元素对象的值,语法为“行元素对象.html(修改后的值)”。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008