注意:keep-alive 一定要放在变化的模块化里面
app.vue里面有一个router-view 在哪里放keep-alive没有效果
因为我在home里面写的模块化 所以要在home页面里面使用keep-alive进行缓存
//头部导航栏
<el-header>
<Nav />
</el-header>
<el-container>
<el-aside>
//侧面导航栏
<Sidebar />
</el-aside>
<el-main>
<!-- 兼容使用了插槽的页面 -->
<router-view v-slot="{ Component }">
<keep-alive :include="crumbs" max="12">
<component :is="Component" />
</keep-alive>
</router-view>
</el-main>
</el-container>
核心代码:
<!-- 兼容使用了插槽的页面 -->
<router-view v-slot="{ Component }">
<keep-alive :include="crumbs" max="12">
<component :is="Component" />
</keep-alive>
</router-view>
:include="crumbs" 是获取面包屑的页面命名来规定那些页面要缓存
max是控制最大缓存页面数量
home页面 获取保存的面包屑列表数据
data() {
return {
crumbs: []
}
},
watch: {
$route: {
immediate: true,
handler(val, oldval) {
let arr:any = sessionStorage.getItem("crumbs")
// console.log("获取面包屑列表", JSON.parse(arr));
this.crumbs = JSON.parse(arr)
// console.log("面包屑",this.crumbs);
}
},
},
route页面
每个页面的name必须是唯一的并且要和这里路由的name相同
上面的name和path和meta下面meta的name和path必须相同
{
path: "index",
name: "IndexView",
component: () => import('@/views/Index/Index.vue'),
props: true,
meta: {name: "IndexView", path: "/index", title: "首页" },
},
面包屑页面:做增加删除保存操作
<template>
<div class="nav">
<h1 @click="go">后台管理系统</h1>
<!-- 面包屑 -->
<div class="container">
<el-menu :default-active="$route.path" :router="true" class="list">
<el-menu-item class="li" v-for="(item, index) in menuData" :index="item.path" :key="index"
:to="{ path: item.path }">
{{ item.title }}
<!-- 这里index是让第一个不显示删除 禁止不在当前页面删除该页面,因为删除了其他页面没有跳转路由就不会刷新缓存马上点刚才删除的页面缓存还在所以必须要跳转页面刷新缓存,使用vuex监听缓存列表变化也不行,必须要跳转页面才会刷新缓存 -->
<img v-if="index && $route.path == item.path" @click.stop="del(index, item.path)" src="@/assets/shanchu.png" alt="删除" width="100%">
</el-menu-item>
</el-menu>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import { ElMessage } from "element-plus";
import { useStore } from "vuex";
import { useRouter } from 'vue-router'
export default defineComponent({
name: 'NavView',
components: {},
data() {
return {
menuData: [], //面包屑路径
}
},
setup() {
const store = useStore();
const router = useRouter()
return {
store, router
}
},
mounted() {
this.menuData = JSON.parse(sessionStorage.getItem('menuData') as string) || [{ title: "首页", path: "/index", name: "IndexView" }]
this.newmenuData()
},
watch: {
$route: {
immediate: true,
handler(val, oldval) {
// console.log(this.$route.meta.title);
// console.log(this.$route.meta.path);
let arr: any = this.menuData
let yes: any = true //是否添加进去
arr.forEach((item: any) => {
// 判断是否有重复路由 没有才添加
if (item.path == this.$route.meta.path) {
yes = false
}
});
if (yes) {
let obj: any = {
"title": this.$route.meta.title,
"path": this.$route.meta.path,
"name": this.$route.meta.name
}
arr.push(obj)
this.menuData = arr
this.newmenuData()
}
if (this.menuData.length > 12) {
// 缓存页面home里面设置了缓存最大值为12
this.menuData.splice(1, 1)
this.newmenuData()
}
}
},
},
methods: {
// 清除单个面包屑
del(i: any, path: never) {
// console.log(i, path);
// console.log(this.menuData);
if (this.$route.path == path && i != '0') {
let arr: any = this.menuData[i - 1]
// console.log(arr.path);
this.$router.push(arr.path)
}
this.menuData.splice(i, 1)
// 主动删除可能只有一个
sessionStorage.setItem("menuData", JSON.stringify(this.menuData))
this.newmenuData()
},
// 更新面包屑和缓存列表
newmenuData() {
// 大于1防止刷新保存初始化数据
this.menuData.length > 1 && sessionStorage.setItem("menuData", JSON.stringify(this.menuData))
let arr: any = []
this.menuData.forEach((item: any) => {
arr.push(item.name)
})
console.log("更新缓存列表", arr);
sessionStorage.setItem("crumbs", JSON.stringify(arr))
},
}
});
</script>
<style lang="less" scoped>
.container {
-webkit-user-select: none;
box-sizing: border-box;
max-height: 53px;
}
.list {
height: 53px;
box-sizing: border-box;
display: flex;
justify-content: start;
background-color: #242a33;
border-right: 1px solid #242a33;
.li {
height: 53px;
color: #FFFFFF;
cursor: pointer;
box-sizing: border-box;
&:hover {
background-color: #1a1f25;
color: coral;
}
&:hover img {
opacity: 1;
}
img {
z-index: 100;
vertical-align: middle;
width: 15px;
margin-left: 10px;
opacity: 0;
}
}
}
// 选中的样式
/deep/ .el-menu-item.is-active {
background-color: rgba(181, 228, 236, 0.377);
color: coral !important;
img {
opacity: 0;
}
}
</style>
解决第一次进入页面不缓存问题
以上代码有一个问题,就是第一次点击进入页面不会缓存页面,第二次才会缓存页面
因为是在监听路由跳转之后添加的缓存路由列表,所以第一次点击进入页面的时候这个页面并没有在缓存列表里面,是进入这个页面之后才添加到缓存列表里面的,所以第二次进入页面才开始执行缓存的,所以需要在跳转之前添加到缓存列表里面
在router路由页面里面写,在跳转之前添加到缓存列表
router.beforeEach((to, from, next) => {
// 在跳转之前把当前路由加入缓存列表
const arr: any = JSON.parse(sessionStorage.getItem("crumbs") as string) || [];
if (!arr.includes(to.name)) {
arr.push(to.name);
sessionStorage.setItem("crumbs", JSON.stringify(arr));
}
})