资讯专栏INFORMATION COLUMN

React 渲染机制解析

荆兆峰 / 1144人阅读

摘要:渲染过程我们都知道使用可以使得网页的性能有很大的提高,本文具体探究它是通过什么样的渲染机制做到的。也就是说如果父节点不同,将不会在去对比子节点。

React渲染过程

我们都知道使用React可以使得网页的性能有很大的提高,本文具体探究它是通过什么样的渲染机制做到的。

在页面一开始打开的时候,React会调用render函数构建一棵Dom树,在state/props发生改变的时候,render函数会被再次调用渲染出另外一棵树,接着,React会用对两棵树进行对比,找到需要更新的地方批量改动。

Diff 算法

这个过程中,比较两棵Dom tree高效找出需要更新的地方是很重要的。React基于两个假设:

两个相同的组件产生类似的DOM结构,不同组件产生不同DOM结构

对于同一层次的一组子节点,它们可以通过唯一的id区分

发明了一种叫Diff的算法,它极大的优化了这个比较的过程,将算法复杂度从O(n^3)降低到O(n)。

同时,基于第一点假设,我们可以推论出,Diff算法只会对同层的节点进行比较。如图,它只会对颜色相同的节点进行比较。

也就是说如果父节点不同,React将不会在去对比子节点。因为不同的组件DOM结构会不相同,所以就没有必要在去对比子节点了。这也提高了对比的效率。

下面,我们具体看下Diff算法是怎么做的,这里分为两种情况考虑

节点类型不同

节点类型相同,但是属性不同

不同节点类型

对于不同的节点类型,react会基于第一条假设,直接删去旧的节点,新建一个新的节点。

比如:


  

// 由shape1到shape2

  

React会直接删掉A节点(包括它所有的子节点),然后新建一个B节点插入。

为了验证这一点,我打印出了从shape1到shape2节点的生命周期,gitbub链接:
https://github.com/hhhuangqio...

感兴趣的可以自己跑一跑代码~

Shape1 :
A is created 
A render
C is created
C render
C componentDidMount
A componentDidMount

Shape2 :
A componentWillUnmount
C componentWillUnmount
B is created
B render
C is created
C render
C componentDidMount
B componentDidMount

由此可以看出,A与其子节点C会被直接删除,然后重新建一个B,C插入。

相同节点类型

当对比相同的节点类型比较简单,react会对比它们的属性,只改变需要改变的属性

比如:

这两个div中,react会只更新className的值

这两个div中,react只会去更新color的值

列表比较

// 列表一到列表二

从列表一到列表二,只是在中间插入了一个C,但是如果没有key的时候,react会把B删去,新建一个C放在B的位置,然后重新建一个节点B放在尾部。

你说什么就是什么咯?!不信的话,我们还是跑一边代码,看看生命周期验证一下

列表一:
A is created
A render
B is created
B render
A componentDidMount
B componentDidMount

列表二:
A render
B componentWillUnmount
C is created
C render
B is created
B render
A componentDidUpdate
C componentDidMount
B componentDidMount

当节点很多的时候,这样做是非常低效的,所以我们需要给每个节点配一个key,让react可以识别出来哪些节点是一样的,不需要重新创建。
配上key之后,在跑一遍代码看看,

A render
C is created
C render
B render
A componentDidUpdate
C componentDidMount
B componentDidUpdate

果然,配上key之后,列表二的生命周期就如我所愿,只在指定的位置创建C节点插入。
这里要注意的一点是,key值必须是稳定(所以我们不能用Math.random()去创建key),可预测,并且唯一的。

小结

React整个的渲染机制就是在state/props发生改变的时候,重新渲染所有的节点,构造出新的虚拟Dom tree跟原来的Dom tree用Diff算法进行比较,得到需要更新的地方在批量造作在真实的Dom上,由于这样做就减少了对Dom的频繁操作,从而提升的性能。

探索性能优化

但是,是不是真的需要对所有的节点都重新渲染一遍呢?
下一篇文章,我们将继续探讨这个问题~

参考文档:

http://www.infoq.com/cn/artic...

https://facebook.github.io/re...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/84678.html

相关文章

  • 浅谈React Fiber

    摘要:因为版本将真正废弃这三生命周期到目前为止,的渲染机制遵循同步渲染首次渲染,更新时更新时卸载时期间每个周期函数各司其职,输入输出都是可预测,一路下来很顺畅。通过进一步观察可以发现,预废弃的三个生命周期函数都发生在虚拟的构建期间,也就是之前。 showImg(https://segmentfault.com/img/bVbweoj?w=559&h=300); 背景 前段时间准备前端招聘事项...

    izhuhaodev 评论0 收藏0
  • Record 前端开发知识整理分享

    showImg(https://segmentfault.com/img/remote/1460000018716142?w=200&h=200); showImg(https://segmentfault.com/img/remote/1460000018716143);showImg(https://segmentfault.com/img/remote/1460000010953710);...

    TZLLOG 评论0 收藏0
  • 初级前端开发面试总结

    摘要:前端面试总结先说背景,本人年月毕业,去年十月校招到今年月一直在做前端开发工作,年前打算换工作,就重新梳理下面试考点总结包含基础,基础,常见算法和数据结构,框架,计算机网络相关知识,可能有的点很细,有的点很大,参考个人情况进行总结,方便对知识 前端面试总结 先说背景,本人2018年7月毕业,去年十月校招到今年10月一直在做前端开发工作,年前打算换工作,就重新梳理下面试考点总结包含: ...

    jifei 评论0 收藏0
  • 初级前端开发面试总结

    摘要:前端面试总结先说背景,本人年月毕业,去年十月校招到今年月一直在做前端开发工作,年前打算换工作,就重新梳理下面试考点总结包含基础,基础,常见算法和数据结构,框架,计算机网络相关知识,可能有的点很细,有的点很大,参考个人情况进行总结,方便对知识 前端面试总结 先说背景,本人2018年7月毕业,去年十月校招到今年10月一直在做前端开发工作,年前打算换工作,就重新梳理下面试考点总结包含: ...

    tigerZH 评论0 收藏0
  • 2017文章总结

    摘要:欢迎来我的个人站点性能优化其他优化浏览器关键渲染路径开启性能优化之旅高性能滚动及页面渲染优化理论写法对压缩率的影响唯快不破应用的个优化步骤进阶鹅厂大神用直出实现网页瞬开缓存网页性能管理详解写给后端程序员的缓存原理介绍年底补课缓存机制优化动 欢迎来我的个人站点 性能优化 其他 优化浏览器关键渲染路径 - 开启性能优化之旅 高性能滚动 scroll 及页面渲染优化 理论 | HTML写法...

    dailybird 评论0 收藏0

发表评论

0条评论

荆兆峰

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<