琢磨了很久,如果一个路由里的状态很多,那么如果手动将状态存到redux或者dva或者localStorage里,等路由再次渲染的时候初始化数据是非常麻烦的,但是如果只是将路由的dom节点隐藏,不从dom树中删除,那么就免去了很多数据的存取逻辑,主要的逻辑如下,技术用的是umi+reacthooks+dva+typescript。
如果不熟悉umi的项目框架可以先去学习一下umi的基础,再来看这篇文章。
创建父路由layouts布局,ui设计稿里所有的页面都是基于这个layouts父路由的子路由,我们再layouts.tsx文件下设置要缓存的子路由列表,再dva里设置routeCache.ts用来操作缓存路由实例的存取逻辑,下面是代码的实现逻辑。
1.dva下的routeCache.ts文件
import { IRouteComponentProps } from 'umi'
export interface IRouteCacheProps {
routeCaches: {
key: string;
val: any;
export default {
namespace: 'routecache',
state: {
routeCaches: {}
reducers: {
setRouteCaches(state: IRouteCacheProps, actions: { payload: { key: string; val: any } }) {
const { payload } = actions
const newRouteCaches = {
...state.routeCaches,
[payload.key]: payload.val
return {
...state,
routeCaches: newRouteCaches
clearRouteCaches(state: IRouteCacheProps){
return {
...state,
routeCaches: {}
subscriptions: {
setup(props: IRouteComponentProps) {
const { history } = props
history.listen((historyRes: any) => {
2.layouts/layouts.tsx文件
import React, { useEffect } from 'react';
import Styles from './layouts.less'
import { useSelector, useDispatch, IRouteComponentProps } from 'umi'
import { IRouteCacheProps } from '@/models/routecache';
import { UMI } from '@/pages/keepalive/k1'
const KEEP_ALIVE_ROUTE: string[] = [
'/main/k2',
'/main/k3'
interface IProps {
name: string;
color: string;
[propName: string]: any;
export default (props: IRouteComponentProps) => {
const a: UMI.IOneProps = { name: 'string' }
const { pathname } = props.location
const CacheRouteState = useSelector((state: { routecache: IRouteCacheProps }) => state.routecache);
const dispatch = useDispatch()
useEffect(() => {
if (KEEP_ALIVE_ROUTE.includes(pathname)) {
const { routeCaches } = CacheRouteState as any;
if (!routeCaches[pathname]) {
const currentRouteIndex = props.children.props.children.findIndex((op: any)=>op.props.path===pathname)
dispatch({
type: 'routecache/setRouteCaches',
payload: {
key: pathname,
val: props.children.props.children[currentRouteIndex]
}, [pathname])
return (
<div className={Styles['layouts']}>
{}
(Object.entries(CacheRouteState.routeCaches) || []).map(([routeName, routeVal]) => {
return <div key={routeName} className={pathname === routeName ? `${Styles['layouts-show']} cache`: `${Styles['layouts-hide']} cache`}>{
routeVal.props.render()
}</div>
!KEEP_ALIVE_ROUTE.includes(pathname) ?
<div className={Styles['layouts-show']}>{props.children}</div> :
</div>
当然这种处理方法还是有一些弊端,如进入缓存的路由只能用visibilitychange事件,离开和进入想触发的事件还是不好处理,欢迎大佬们指点。
琢磨了很久,如果一个路由里的状态很多,那么如果手动将状态存到redux或者dva或者localStorage里,等路由再次渲染的时候初始化数据是非常麻烦的,但是如果只是将路由的dom节点隐藏,不从dom树中删除,那么就免去了很多数据的存取逻辑,主要的逻辑如下,技术用的是umi+reacthooks+dva+typescript。如果不熟悉umi的项目框架可以先去学习一下umi的基础,再来看这篇文章。创建父路由layouts布局,ui设计稿里所有的页面都是基于这个layouts父路由的子路由,我们再lay
v6相比v5,做了很多的优化。包括书写上更加的便捷,更加体现组件化思想。以往在处理路由嵌套和鉴权方面,v5的写法都靠各自开发人员去实现相对比较参差不齐。一下针对v6的配置做简单的介绍。
二、useRoutes
v6中路由的设置采用hook的方式,有点像vue的router的实例化。
import {useRoutes} from "react-router-dom";
import { Suspense, lazy } from 'react'
const routes = [
本篇算是读书笔记,书是《深入理解React Router:从原理到实践》
以下代码实现基于react-router5
在React Router中,一般情况下原生Route所负责渲染的组件在命中路由时进行挂载,而在导航时离开,路由未命中时组件将被销毁,分别对应了组件的componentDidMount与componentWillUnmount生命周期。
如果想在导航后页面得到缓存呢?在Vue或Angular中,有对应的keep-alive与路由复用策略可以实现页面缓存,React Router没有提供。一般
react-keepalive-router
基于react 16.8+ , react-router 4+开发的react缓存组件,可以用作缓存页面组件,类似vue的keepalive封装vue-router的效果功能。
采用react hooks全新api ,支持缓存路由,手动解除缓存,增加了缓存的状态周期,监听函数等。
后续版本会完善其他功能。
缓存组件+监听
二快速上手
npm install react-keepalive-router --save
yarn add react-keepalive-router
1基本用法
KeepaliveRouterSwitch
KeepaliveRouterSwitch可以理解为常规的Switch,也可以理解为keepaliveScope ,我们确保整个缓存作用域,只有一个KeepaliveRou
react-router-cache-route 是路由缓存工具,通常在dva的首页app.js中一起搭配使用
但是需要注意的是,每一个route路由路径在定义的时候,都需要指定是否需要cache,如果使用copy大法,很容易忽略
这会导致一种后果,即从路由A点击跳转进入路由B,再由路由B点击返回路由A,最后再次点击跳转进入路由B,打印后会发现,路由B对应的组件没有被重新加载,这正是因为route.js中的配置,配置成了cache=true
import { Router, Route } from
react-router-cache-route — 页面缓存插件
此插件可以满足缓存上一页的功能,即:返回上一页的时候,上一页的滚动条、动作状态等等和离开这个页面时的状态保持一致。
搭配 react-router 工作的、带缓存功能的路由组件,类似于 Vue 中的 keep-alive 功能。
Route 中配置的组件在路径不匹配时会被卸载(render 方法中 return null),对应的真实节点也将从 dom 树中删除,利用Route暴露的children方法,让我们手动控制渲
CSDN-Ada助手:
react &; taro 报错 _createSelectorQuery is not defined解决办法
QingHan_wow:
react &; taro 报错 _createSelectorQuery is not defined解决办法
周栖-little:
vue动态路由 this.$router.addRoutes
xtcgjk:
vue动态路由 this.$router.addRoutes
QingHan_wow: