一、概述

为了在React中实现类似Keep-Alive的组件行为,之前对市面上目前所存在的一些主流实现库及其原理进行了调研总结。通过对比选择,最终得出以下三个实现方案是我们认为初步可行的:

方案 优点 缺点
组件级别缓存:react-activation 缓存粒度细 破坏DOM结构导致React 合成事件冒泡失效(基本无法修复)
路由级别缓存:react-router-cache-route 使用人数多、范围广 只支持react-router@5.x.x
路由级别缓存:自研react-router@6 Keep-Alive 支持最新的react-router@6.x.x 需要自己实现,有一定成本

可以看到,目前并没有一个完美成熟且低成本的解决方案能够为我们所用。

经过对其实现原理的研究及讨论,我们认为目前情况下使用自研方案是一个最优解,其原因有以下几点:

  1. 自研方案代码设计实现并没有想象中的复杂,实现成本可控;
  2. 自研方案能够摆脱应用框架实现keep-alive只能停留在react-router@5.x.x的桎梏,让框架的生命力更长久;
  3. 自研keep-alive方案底层实现逻辑与react-router-cache-route一致,使用css display属性控制缓存组件的展现,并无破坏DOM结构等hack代码,实现逻辑可靠;

因此,以下内容主要围绕自研Keep-alive方案该如何设计实现展开。

二、方案设计

img

2.1 基础组件

为使用者提供三个基础组件来实现keep-alive基础功能:

1. CacheRoutes

组件用来包裹所有希望缓存的路由组件(将其渲染并存储在该组件下),应放置于所有希望缓存的CacheRouter组件最外层,避免react将其卸载。

2. CacheOutlet

组件用来包裹所有希望缓存的嵌套路由组件(将其渲染并存储在该组件下),应放置于所有希望缓存的CacheRouter嵌套路由组件最外层,避免react将其卸载。、

3. CacheRoute

组件用来包裹希望缓存的自定义组件,与Route组件一致在同一级别出现,CacheRoute标明该组件内的自定义组件需要被缓存。

此外该组件将支持一些行为拓展参数如when(用以决定何时使用缓存功能,forward/back/always)等等,

2.2 生命周期

为使用者提供两个生命周期函数,让使用者能够感知到缓存组件的展示情况,根据展示与否执行相关自定义逻辑:

1. useActive

缓存组件展示时调用传入其中的函数

2. useDeactive

缓存组件隐藏时调用传入其中的函数

2.3 缓存清除

为使用者提供相关函数,赋予其手动清除缓存的能力:

1. dropByCacheKey

调用时通过缓存组件的key值清除其缓存

2. clearCache

调用时清除全部缓存

2.4 质量保证

提供较为完善的单元测试,并在实际项目中使用尝试