实现代码
在进行vue项目开发中,会遇到一些关于页面缓存的 需求 比如:
- a、b、c 三个页面
- a 进入 b,缓存 a页面
- b 进入 c,缓存 a、b 页面
- 离开 c,移除 b 的缓存
- 离开 b,移除 a 的缓存
注意
- 以下代码是从项目中提取出来的,提取后未验证,注意踩坑
- 仅作为
笔记、参考思路
1、新建工具文件
src/utils/keepAliveVerification.js
/**
*
*
* 页面 是否使用 keep-alive 动态验证
* 关键条件:meta.cachedRouteNames
* 获取缓存条件,例:a页面访问b页面,在a页面路由的meta.cachedRouteNames中,是否存在 b页面的路由名称,存在则表示缓存(表示路由是从a页面进入的b页面)
*/
import store from "@/store/index";
// 从公共模块中读取 需要缓存的路由名称
const { cachedRouteNames } = store.state.common;
// 路由发生改变
const changeRoutes = (route, type) => {
// 得到 路由对应的组件名称
const routeComponentName = route.components.default.name;
if (
routeComponentName && type === "add"
? !cachedRouteNames.includes(routeComponentName)
: cachedRouteNames.includes(routeComponentName)
) {
store.commit("common/update_cachedroutenames", {
action: type,
route: routeComponentName
});
}
};
// 定义添加缓存组件name函数,设置的时组件的name
const addRoutes = route => {
changeRoutes(route, "add");
};
// 定义删除缓存组件name函数,设置的是组件的name
const deleteRoutes = route => {
changeRoutes(route, "delete");
};
// 配置路由keepAlive状态
const setRouterBeforeEach = router => {
// 路由守卫
router.beforeEach((to, from, next) => {
// 获取缓存条件,例:a页面访问b页面,在a页面路由的meta.cachedRouteNames中,是否存在 b页面的路由名称
const fromCachedRouteNames = from.meta.cachedRouteNames;
// 获取当前路由所在的路由信息
const fromRoute =
from && from.matched instanceof Array
? from.matched[from.matched.length - 1]
: null;
// 读取前往界面的路由结构,前往的界面存在多级嵌套(多层布局方式包裹)
to.matched.forEach((item, index) => {
// 当 index 小于 路由嵌套层级,追加 路由层级嵌套组件结构
if (index < to.matched.length - 1) {
// 如果使用了 keepAlive
if (item.meta.keepAlive) {
addRoutes(item);
} else {
deleteRoutes(item);
}
} else if (index === to.matched.length - 1) {
// 如果路由访问的真实地址(路由嵌套层级的最后一层),在当中的条件满足判断后,即:a页面缓存条件是(从a页面进入的b页面,才进行缓存a页面)
if (
from.meta.keepAlive &&
(fromCachedRouteNames && fromCachedRouteNames.includes(item.name))
) {
// 缓存当前页面
addRoutes(fromRoute);
} else {
// 不存在,删除当前路由的 缓存信息
deleteRoutes(item);
}
}
});
next();
});
};
export default {
setRouterBeforeEach
};
2、配置 store module
src/store/modules/common.js
/***
*
* 公共文件,用于 存储页面动态缓存(keep-alive)
*
*/
const UPDATE_CACHEDROUTENAMES = "update_cachedroutenames";
const state = {
// 页面activated时是否需要重新加载
activatedReloadData: true,
// 缓存的路由列表
cachedRouteNames: []
};
const mutations = {
[UPDATE_CACHEDROUTENAMES](st, { action, route }) {
const methods = {
add: () => {
st.cachedRouteNames.push(route);
},
delete: () => {
st.cachedRouteNames.splice(
st.cachedRouteNames.findIndex(e => e === route),
1
);
}
};
methods[action]();
}
};
export default {
namespaced: true,
state,
mutations
};
3、导入配置的 store module
src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
......
import common from './modules/common'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
......
common
},
getters
})
export default store
4、页面 layout文件中,添加 keep-alive include 配置
src/layout/AppMain.vue
<template>
<section class="app-main">
<transition name="fade-transform" mode="out-in">
<keep-alive :include="cachedViews">
<router-view />
</keep-alive>
</transition>
</section>
</template>
<script>
export default {
name: "AppMain",
computed: {
cachedViews() {
// 动态缓存配置
return this.$store.state.common.cachedRouteNames;
}
},
};
</script>
5、使用 动态缓存 工具函数
src/main.js
......
// 导入路由
import router from './router'
// 导入 keey-alive缓存 动态验证文件
import keepAliveVerification from './utils/keepAliveVerification.js';
// 配置路由keepAlive状态
keepAliveVerification.setRouterBeforeEach(router);
6、路由结构变更
- src/router/index.js
// 导入布局文件
import Layout from "@/layout/AppMain.vue";
// 页面导出的路由配置
export const constantRoutes = [
......
{
path: "/user",
component: Layout,
redirect: "/userList",
children: [
{
name: "Homr",
path: "/userList",
hidden: true,
component: resolve => require(["@/views/user-list/index.vue"], resolve),
hidden: true,
meta: {
title: "用户列表页面",
icon: "user-list-icon",
cachedRouteNames:['userDetail'],// 说明:当进入 userDetail 页面时,缓存当前页面
},
children: [
{
name: "userDetail",
path: "/userList/detail",
hidden: true,
component: resolve => require(["@/views/index/detail/index.vue"], resolve),
meta: {
title: "用户详情界面",
},
}
]
}
]
}
]
写在最后
如有问题,欢迎指教,共同学习