最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Recoil 源码探索

    正文概述 掘金(豆皮范儿)   2021-04-06   540

    Hello,豆皮范儿同学们,字节跳动春招开始了,大家ready了吗?欢迎大家找我内推,或者进入团队号投递简历。

    接下来我们请来了字节跳动数据平台的xx带来的《Recoil 源码探索》,让我们一起学起来,造起来,也是一种不错的状态解决方案。

    1. 简介

    Recoil 是 facebook 推出的一个状态解决方案,主要的特点有:1. 高性能的渲染,2. 通过状态生成派生值。

    2. 特点

    高性能渲染

    Recoil 源码探索

    在 List 和 Canvas 中的第二个子组件中,如果有状态需要进行共享,常见的方法是,将状态提升到最近的公共祖先节点上,但是这样带来的问题是,如果不进行额外的处理,会造成全局的重新渲染。当然,可以使用 useMemo + immutable 进行优化。另外一种解决方法是使用 Context,使用 Context 如果想解决全局渲染的问题,需要将需要共享的值放在一个独立的 Context 中,这样带来的问题是,我们的组件上,如果有更多的状态需要共享,就需要包裹很多的 Provider,维护起来也比较困难。

    Recoil 带来了一个全新的概念 Atom,将状态原子化并分散管理,Atom 是可以进行更新并且被组件所订阅的,只要 Atom 更新,可以精确地对订阅这个 Atom 的组件进行重新渲染。

    Recoil 源码探索

    Recoil 源码探索

    派生值

    可以根据 Atom,生成新的可被组件订阅的数据,类似 Vue 的计算属性。

    Recoil 源码探索

    在这里,更加强大的是,这里的 get 方法里还可以处理异步请求。

    3. 核心过程源码

    初始化

    与 Redux 类似,在使用全局数据时,需要在根组件上包一个组件,在 Recoil 中,需要包裹上组件 RecoilRoot。

    Recoil 源码探索

    对于 RecoilRoot,其实是在我们的业务代码上,包了一层 Context,其中提供了获取 store 中的数据,更新 store 中的数据等方法。

    Recoil 源码探索

    原子状态定义

    Recoil中,将每一个最小的状态单位(即无法从其他状态计算得出)定义为一个 Atom。对于每一个 Atom ,其实返回的是一个对象,包括了 key(这个 key 是从传入的 option 中解构出来的,并且需要全局唯一), 以及提供了 get 和 set 等方法。

    Recoil 源码探索

    对于 Atom 而言,必须有一个 set 方法,因为我们定义一个原子数据,肯定需要对其进行修改,否则是没有意义的。而对于 Atom 而言,其 get 方法相对简单,在 key 存在的情况下,直接从一个状态的 Map 中获取即可。

    Recoil 源码探索

    派生值定义

    对于 selector,也与 Atom 一样,也提供了 get 及其他方法,然而,对于 selector 而言,是可以通过 Atom 得到的,所以 set 方法则不是必须的。

    Recoil 源码探索

    对于 get 方法,也与 Atom 有所不同,selector 的 get 多了一个缓存的处理,在没有缓存的情况下,会根据依赖的 Atom,计算得到对应的值,并将这个值进行缓存,在下次获取的时候,如果依赖的值没有变化,则可以从缓存中取值,尽可能地提高性能。

    Recoil 源码探索

    在组件中 订阅/更新 共享的值

    在 Recoil 中,常见 订阅/更新 的 hooks 有 useRecoilState, useRecoilValue, useSetRecoilState。其中 useRecoilState 包含了其余两个。

    Recoil 源码探索

    订阅值

    Recoil 源码探索

    useRecoilValue 中主要的调用链如下:

    useRecoilValue -> useRecoilValueLoadable -> useRecoilValueLoadable_LEGACY -> subscribeToRecoilValue
    

    Recoil 源码探索

    Recoil 源码探索

    在这里,组件中通过 useRecoilValue(useRecoilState) 使用 Atom 或是 selector,会在组件上增加一个订阅,这个订阅通过 useState 来实现,当对应的 RecoilValue 更新时,对组件进行重新渲染,从而做到最小粒度更新组件。这里十分重要的是,storeState.nodeToComponentSubscriptions.set 的方法,这个方法在全局的 store 上更新了全局唯一的 key 所维护的 subscription map,通过这个 map ,在进行更新值的时候,可以准确找到对应关系,从而触发 forceUpdate 对组件进行重新渲染。

    更新值

    Recoil 源码探索

    useSetRecoilState 中主要的调用链如下:

    useSetRecoilState -> setRecoilValue -> queueOrPerformStateUpdate -> applyActionsToStore -> store.replaceState -> Batcher Effect -> sendEndOfBatchNotifications
    

    这个 store.replaceState 则是在 RecoilRoot 中对 store 进行初始化时设置的方法。

    Recoil 源码探索

    其中的 notifyBatcherOfChange.current 则是在 <Batcher> 组件中通过 useState 的形式进行 state 的更新,从而触发 useEffect,执行 sendEndOfBatchNotifications

    Recoil 源码探索

    Recoil 源码探索

    而最终执行的这个 callback,就是上面订阅值的时候,所注册的 subscription,从而达到精确更新对应的组件。

    这里需要注意的是,如果组件只需要对共享的状态进行更新,不能使用 useRecoilState,因为使用 useRecoilState 的同时会进行共享状态的订阅,造成不必要的渲染。

    4. 总结

    从 Recoil 的源码中,可以了解到其通过订阅和更新的分离,确保最小粒度的渲染,以及最小化了数据的单位,利用 selector 产生的派生值进行缓存,提高了计算的效率。


    起源地下载网 » Recoil 源码探索

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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