背景
引用了路由页面的跳转react-router-dom,页面切换过程中未有堆栈路由支持,故在众多实现方式中选中了react-activation,不过它的实现是对组件进行缓存(也就成为后面报错后一直纠结的点),而不是路由缓存. 不过还是可以支持业务优化的效果!
实现
直接参考文档即可,还是很详细的,这边主要说说避开的坑
问题解决
报错: Cannot create property 'name' on string 'react-activation/babel'
按照文档配置后,发现原来如果引用了博主提供的react-activation/babel
在本地运行时没问题的,但是打包后就会出现以上的报错。解决方式参考,主要的问题是需要对vite单独做兼容引用,而原本的babel是对webpack的使用
报错: useLocation() may be used only in the context of a component.
已经按照了文档配置了一遍后,一开始以为插件是组件缓存,如果我在路由表配置成如下
<Route path="/" element={
<KeepAlive name='index' key="index" navigate={useNavigate()}><Navigate to="/index" /></KeepAlive>
}/>
那可能影响路由的编译,于是恢复成原有路由表格式,只保留组件缓存的页面,发现跳过去也会出现这个问题😩😩😩,显然不是配置问题(因为单独跳到缓存的组件也会报错,故基础配置问题出现)
通过作者了解
<Provider store={store}>
<div>
<React.Suspense >
<BrowserRouter>
<AliveScope>
<RouterComponent />
</AliveScope>
</BrowserRouter>
</React.Suspense>
</div>
</Provider>
还需在router表中再嵌套多一层解决AliveScope
才可以正常运行,一开始以为在App.tsx已经有AliveScope
嵌套,所以以为不用了。
项目实现的思考
基于只对组件缓存而不是路由缓存的问题。如果从组件要引生到页面缓存,那么我们需要对KeepAlive
区分好唯一值key,在跳转的时候KeepAlive
就根据key值去区分是否当前已经有没缓存。
选择这个插件的原因也就是刷新页面后组件缓存就不存在了,对PC实现效果很友好
路由表设计
部分页面可以在路由中以组件方式存在缓存,定好key值,那么可以实现,只要对要缓存的路由KeepAlive
包裹即可
//index
import Activation,{ KeepAlive,AliveScope }from 'react-activation'
const RouterComponent:any = () => (
<Routes>
<Route path="/" element={
<KeepAlive name='index' key="index" navigate={useNavigate()}><Navigate to="/index" /></KeepAlive>
}/>
</Routes>
//路由表,我还是有用懒加载去实现
{
pathname: '/mine',
name: 'Mine',
component: ReactLazilyComponent(() => import('@/pages/mine'))
},
BrowserRouter 的写法
参考如上问题二即可,内嵌多AliveScope
,在app.tsx也是需要
<AliveScope>
<App />
</AliveScope>
页面设计
如果遇上详情页,同样的路由,只是拼接携带的参数不同,那么在routes表中是无法解决的,毕竟,路由表中只能接收/:id
的值,很多时候往往我们设计不是如此,比如?id=1&type=1
这样的方式
这边是直接通过将页面的index.jsx文件提取一个单独的文件,直接在用Activation
包裹住,由于KeepAlive
中的key值会被插件加上前缀重新定义的,所以很难定位到,可是name
值不变,故运用不会被改变的name
值去做处理
// home/index
import Activation,{ useActivate , useAliveController } from 'react-activation'
const GeneralPages = () => {
const [search, setSearch] = useSearchParams()
import { useSearchParams } from 'react-router-dom'
const key = search.get('type')
return (
<Activation
name={key} //必须要的,通过它去清楚缓存
id={key}
key={key} //必须要的,这个记录缓存是否重复
>
<GeneralPagesIndex/>
</Activation>
)
}
export default GeneralPages
//home/GeneralPagesIndex
//如果你是函数式开发,并且你是在原有代码上做缓存,你可以直接全部拷贝过去,在通过组件引用的方式读取
const GeneralPagesIndex = () => {
//超级多内容的呃
}