嵌套路由
路由一定只能嵌套一层children即只有一个router-view 要不切换其他层级的路由缓存会消失 原因:
- 缓存是存储在children的route-view上的
- 路由的component不能为空,当有时为了统一规范,需要一个空的component时,路由的component为这样写
<template>
<keep-alive>
<router-view />
</keep-alive>
</template>
<script>
export default {
name: "ParentView",
data() {
return {};
},
computed: {},
};
</script>
<style lang="less" scoped></style>
解决方案 直接将多余的route-view删除
// 路由守卫,跳转后处理
router.afterEach((to) => {
handleKeepAlive(to);
});
/**
* 递归处理多余的 layout : <router-view>,
* 让需要访问的组件保持在第一层 index : <router-view> 之下
* @param to
*/
function handleKeepAlive(to) {
if (to.matched && to.matched.length > 2) {
for (let i = to.matched.length - 1; i >= 0; i--) {
const element = to.matched[i];
// 因为import()异步懒加载,第一次获取不到element.components.default.name , 所以不能再beforeEach做,不然第一次访问的界面不缓存第二次才会缓存
// afterEach就不一样了,这时候可以获取到element.components.default.name了
if (element.components.default.name === "ParentView") {
to.matched.splice(i, 1);
}
}
}
}
路由带参数时缓存无法删除
include 只有名称匹配的组件会被缓存(名称指的是组件中定义的name) 同一个组件的name是一样的,修改include时,如果name还存在那么就不会删除
解决方案 在tab页删除时手动删除缓存
<template>
<页签Tab组件 @删除页签="removeTab($event)"></页签Tab组件>
<keep-alive :include="cacheList">
<router-view ref="routerView" :key="tabId" />
</keep-alive>
</template>
<script>
removeTab(tabId) {
if (!this.$refs.routerView) {
return;
}
let { cache, keys } =this.$refs.routerView.$vnode.parent.componentInstance;
if (tabId in cache) {
// 手动销毁组件
cache[tabId].componentInstance.$destroy();
cache[tabId].componentInstance = undefined;
delete cache[tabId];
}
let index = keys.findIndex((a) => a == fullPath);
if (index >= 0) {
keys.splice(index, 1);
}
}
</style>
实际使用发现
delete cache[fullPath]没有生效,并不会删除object的key