react中由缓存功能引发版本更新的血案(react-router-cache-router缓存组件,react-router-dom5,路由鉴权修改,异步组件修改,hook,@connect)
react实现缓存功能首先React Router 必须确保是 最新版本,因为使用了 new Context,所以必须确保Router 使用相同的 API,
之前的项目我们采用的是react-router3.xx版本,想都不用想,这将到这我们的项目中要改一些别人舍弃的东西。。。
一、react-router5
新版本的router不支持route里面嵌套route,可以放到另一个组件中去配置,这样我们之前的路由鉴权需修改,另外新版本的异步组件也不支持getComponent了,需修改,有的页面需要缓存的(例如列表页进详情页,详情页回来的时候最好能缓存列表页,一是优化,减少请求,而是记住滚动位置或者页数优化用户体验),这就需要cache-router,需对路由修改,
异步组件: 可以参照我写的 https://blog.csdn.net/qzf_hainenggaima/article/details/103163062 除了
第二种都能用,推荐第一种;
路由鉴权: 即跳转拦截,(除了接口的请求响应拦截我们这里需要路由跳转拦截)比如token过期跳转到登录页,我们修改之前的路由,封装私有路由函数,
function PrivateRoute({ children, ...rest }) {
let token=localStorage.getItem("token");
return (token? (children) : (
<Redirect
to={{
pathname: "/login",
state: { from: location }
}} />)
)
}
<Router >
<Switch>
<Route exact path='/login' render={ ({match}) =><Login/>}>
<PrivateRoute>
<App/>
</PrivateRoute>
<Route exact path='*' render={ ({match}) =><Notfound/>}/>
</Switch>
</Router>
ok了
缓存组件: 我采用的是 react-router-cache-router ,可以先看下这个例子
https://github.com/qiuzhaofeng/react-router-catch-router5-demo
然后只需要将之前的route更换成CacheRoute,Switch更换成CacheSwitch,这里需要注意的一点是,如果你想使用react-router-cache-router 提供的生命周期钩子,在CacheRoute上不要使用render,换成component,这时候你可能问,为什么使用生命周期钩子,
这里说一个pc端的场景:列表页进详情页需要缓存列表页,但是PC端有些需求是其它页进列表页重新请求,不拿缓存中的数据,咋办,像vue中keep-alive提供了生命周期activated,
咱们这有props.cacheLifecycles.didRecover(this.componentDidRecover)钩子,缓存被恢复时调用this.componentDidRecover,
// 缓存被恢复时触发,
componentDidRecover = () => {
console.log(this.props.isCache, 9999)
// 详情返回时缓存,然后立马将标识初始化,其他页面进来时不缓存,重新请求
if (this.props.isCache) {
console.log(1)
// this.props.changeCache(false)
this.props.getChangeCacheAction(false)
} else {
console.log(2)
this.onChangeCurPageOrPageSize(1, 5)
}
}
这里我把从详情进到列表页时在store中加了一个标识,@connect会减轻你的工作量,进入列表页时标识去了,以至于其他页面进来的都去重新请求页面。
二、hook
由于我们的项目中之前全是class,太多了,就没用hook的方式,但是这将导致react-router中一些api使用不了,例如useHistory ,useLocation,也就是路由跳转等没法玩了,但是可以用withRouter和路由联系起来,这样我们就可以使用this.props.history.push()了。
这里提一下跳转传参当刷新时参数丢失的问题,这是可以放到
his.props.history.push({
pathname:"",
search: ""
})
中。