图解React Diff算法及新架构Fiber

简介: 阿里云前端工程师靖鑫带来了React高阶组件在业务场景中的应用。首先从高阶组件的思想开始谈起,帮助我们灵活管理代码,介绍了简单的HOC示例、传递参数的HOC示例、反向继承HOC,进而讲述了HOC库recompose,然后通过图解重点说明了DOM DIFF算法,最后对新架构Fiber进行了简要介绍。

阿里云前端工程师靖鑫带来了React高阶组件在业务场景中的应用。首先从高阶组件的思想开始谈起,帮助我们灵活管理代码,介绍了简单的HOC示例、传递参数的HOC示例、反向继承HOC,进而讲述了HOC库recompose,然后通过图解重点说明了DOM DIFF算法,最后对新架构Fiber进行了简要介绍。


数十款阿里云产品限时折扣中,赶快点击这里,领券开始云上实践吧!

直播视频精彩回顾

以下是精彩视频内容整理:

什么是高阶组件?

所谓高级组件本质上就是一个函数,接收一个组件后返回另外一个新的组件,这么做的意图就是为了增强(enhance),比如装饰、增添行为、增添逻辑等,都可以放在高阶组件中,高阶组件是一种可以增强组件的能力。

最简单的HOC示例

ac076ff9347e966af26d740e77dddf1b73b4e5ba

如图所示,使用装饰器方式来使用,声明一个函数,定义一个高阶组件,给目标组件包裹一层样式。接收一个组件,返回一个函数式组件props,将props全部解构传递给wrappedcomponent,高阶组件一定不可以影响原来的业务。在此基础上,我们在外面增加一些能力,比如在被包裹的组件外围,由一个card的dom元素包裹在一起。

传递参数的HOC示例

808404938cfc12629b6e43a59ebda784e1820896

首先设置参数,生成特定的HOC,再传递给目标组件使用。定义一个stylefactory方法,返回高阶组件,而不是组件。在高阶组件的前一步做了一层处理,利用闭包思想,它的入参是classname,返回的高阶组件一直内嵌classname。

反向继承HOC

00c34027b89082d22c1b99b21cf504194b1b68bb

前两种高阶组件的特点是不会修改原来的组件,只是在上面包裹一些东西。而有时会更改渲染逻辑,比如当wrappedcomponent资源没有加载回来时,页面显示loading,加载完成后才会显示,这就需要更改显示逻辑。反向继承HOC返回的React组件继承了被传入的组件,既然继承了被传入组件,是不是所有方法都可以使用呢?比如在render方法中渲染出之前的内容,可以直接使用super.render(),我们可以在render方法中重新写一个render,这样原有内容就都展示不出来了,想展示原有内容只需要调用super.render()即可。所以它能够访问到的区域、权限更多,相比属性代理方式,它更像打入组织内部,对其进行修改。

 

脑洞大开的HOC库——recompose

Recompose有很多很多实用的库,下面为大家介绍几个常见场景应用。

e1ead119a750b3d7712a0957470a79c138e729da

第一个情景是展示哪一个。有些时候,你需要根据后端返回值来做决策,例如展示Loading组件,之前你可能会将这部分判断写在render方法里,现在你可以将它们抽离出来了,将判断逻辑提前拿出来,我们的组件尽可能都是函数组件,不需要额外维护状态。顺带也可以将生命周期等方法挪出来,用高阶组件lifecycle代替。

如图所示,高阶组件是一层层被包裹起来的,最里面为wrappedcomponent组件,外部包裹一层branch高阶组件,branch专门用来做条件判断的,根据某一个值去判断真假,如果是真就会直接加载loading组件传递给你的业务组件,如果是假就会把另外一个高阶组件传递给你的业务组件,我们不需要在render方法里做这个判断。然后将代码发起请求的方式拿到lifecycle中去做,lifecycle本身可以写一些生命周期方法,state修改完后传递到branch高阶组件中透传,最终到达业务组件。

674a0d435f9487252ef1dfc97771b894db352637

第二个情景是维护组件自身的State。我们经常会有Tab切换,选择第一个、选择第二个等,将高亮的加上classname,点击展开(收起)等与业务数据无关的状态需要维护,回想以前的代码,我们可能会使用setState,但有时侯state和setstate不是很方便,组件可能非常长,也可能与真实业务代码融合在一起,容易使开发者混淆逻辑。有了recompose,我们可以使用withState和withHandlers来避免手动setState的出现,将展示逻辑和UI进行分离。

7649af3712a0e32015dbd24ec346544dfd690121

第三个情景是组件嵌套。在实际项目中,我们会有多个地方使用到Modal组件,如果都重复一遍上述代码,boilerplate代码将非常多,为此,我们可以将它转变为一个高阶组件,与常规方式不同,我们本次使用recompose提供的HOC来组织我们的代码。

 

DOM DIFF算法简析

b433a32607d8b1a89fa0a44e9155ad7d94e4d8d1

DOM DIFF是react应用中的精华所在,DOM DIFF在使用时有一些约定如下:

1.         DOM节点跨层级的移动操作特别少,可以忽略不计(例如A原本和B平级,随后A变成B的子节点)

2.         拥有相同类的两个组件将会生成相似的树形结构,拥有不同类的两个组件将会生成不同的树形结构(A和B组件结构不一致)

3.         同一层级的一组子节点,它们可以通过uuid进行区分。

DIFF算法在执行时有三个维度,分别是Tree DIFF、Component DIFF和Element DIFF,执行时按顺序依次执行,它们的差异仅仅因为DIFF粒度不同、执行先后顺序不同。

315badd9651f8d79363b01a506e8531759d40bfe

Tree DIFF是对树的每一层进行遍历,如果某组件不存在了,则会直接销毁。如图所示,左边是旧属,右边是新属,第一层是R组件,一模一样,不会发生变化;第二层进入Component DIFF,同一类型组件继续比较下去,发现A组件没有,所以直接删掉A、B、C组件;继续第三层,重新创建A、B、C组件。

5fbd248ebec60d443606aa8e612047d371355a40

如图所示,第一层遍历完,进行第二层遍历时,D和G组件是不同类型的组件,不同类型组件直接进行替换,将D删掉,再将G重建。

27222d09d321b46faeadca9a82dff6164cfbac12

Element DIFF紧接着以上统一类型组件继续比较下去,常见类型就是列表。同一个列表由旧变新有三种行为,插入、移动和删除,它的比较策略是对于每一个列表指定key,先将所有列表遍历一遍,确定要新增和删除的,再确定需要移动的。如图所示,第一步将D删掉,第二步增加E,再次执行时A和B只需要移动位置即可。

 

React Fiber

7d1162dd65baaa56bf26b21d3b4b9bdf52ecdbab

React Fiber是react执行渲染时的一种新的调度策略,JavaScript是单线程的,一旦组件开始更新,主线程就一直被React控制,这个时候如果再次执行交互操作,就会卡顿。

React Fiber重构这种方式,渲染过程采用切片的方式,每执行一会儿,就歇一会儿。如果有优先级更高的任务到来以后呢,就会先去执行,降低页面发生卡顿的可能性,使得React对动画等实时性要求较高的场景体验更好。

文章部分配图来自此文章:https://zhuanlan.zhihu.com/p/20346379

本文由云栖志愿小组毛鹤整理,编辑百见

相关文章
|
1月前
|
JavaScript 前端开发 算法
MVVM模型,虚拟DOM和diff算法
1.MVVM是前端开发领域当中非常流行的开发思想。(一种架构模式)目前前端的大部分主流框架都实现了这个MVVM思想,例如Vue,React等2.虽然Vue没有完全遵循MVVM模型,但是Vue的设计也受到了它的启发。Vue框架基本上也是符合MVVM思想的 3.MVVM模型当中尝到了Model和View进行了分离,为什么要分离?
|
1月前
|
JavaScript 算法
Vue的diff 算法详解
Vue的diff算法是一种用于比较新旧虚拟节点(VNode)的差异并高效更新DOM的技术`**。它的核心在于只对同层级的节点进行比较,避免了跨层级的比较,从而将时间复杂度降低到O(n)
|
3月前
|
JavaScript 算法 前端开发
Vue diff 算法探秘:如何实现快速渲染
Vue diff 算法探秘:如何实现快速渲染
Vue diff 算法探秘:如何实现快速渲染
|
4月前
|
前端开发 JavaScript 算法
react diff 原理
react diff 原理
|
3月前
|
缓存 JavaScript 算法
vue2和vue3之间diff算法的差异
vue2和vue3之间diff算法的差异
|
1月前
|
缓存 JavaScript 算法
Vue.js中的diff算法:让虚拟DOM更高效
Vue.js中的diff算法:让虚拟DOM更高效
|
3月前
|
JavaScript 算法 前端开发
解密Vue 2的Diff算法:如何实现高效的DOM更新?
解密Vue 2的Diff算法:如何实现高效的DOM更新?
|
3月前
|
JavaScript 前端开发 算法
说说React中的虚拟dom?在虚拟dom计算的时候diff和key之间有什么关系?
说说React中的虚拟dom?在虚拟dom计算的时候diff和key之间有什么关系?
18 0
|
3月前
|
算法 JavaScript
什么是diff算法?
什么是diff算法?
17 0
|
3月前
|
存储 算法 JavaScript
Vue3中快速Diff算法
Vue3中快速Diff算法
114 0