vue3 keep-alive 实现页面标签
一、简单效果图展示
二、项目搭建
注:如果已有项目可直接跳过
简单项目搭建如下步骤(文中使用的是vue-cli快速搭建项目):vue-cli官网链接: link(点击跳转)
- 安装Vue CLI(具体步骤看官网),这里注意安装最新版的cli就好;
- 用cli快速生成项目:注意:这里要选中 Manually select features 这个选项
- 选择自己需要的插件,文中用到的有vuex、router、css(按下键,空格选中,回车下一步)
- 接下来会选择使用vue2 还是vue3 ,如果选择了css还会选择使用sass还是less还是Stylus
- 上面的步骤完成了可以直接回车生成项目
三、keep-alive 页面标签简单实现
router.js 路由路径设置
{
path: "/",
name: "home",
redirect: "/home", //重定向到home页面
children: [
{
path: "/home",
name: "HomeView",//注意如果需要换成,name必须是唯一的并且和compnent对应的vue文件中的name一致。
component: () =>
import(/* webpackChunkName: "HomeView" */ "@/views/HomeView.vue"),//这里用了vue cli的懒加载
meta: {
title: "首页",
keepAlive: true,//meta路由元配置是否需要keep-alive缓存
},
},
.......这里根据自己的项目要求设置
]
}
//路由进入之前的钩子函数
router.beforeEach((to, from, next) => {
window.document.title = to.meta.title;//这里设置浏览器的title,如果不需要刻意去掉
to.meta.keepAlive ? store.commit("setLabelDataList", to) : "";//这里的逻辑是为了在打开页面前将路由route的name存入vuex中,方便管理
next();
});
vuex
export default createStore({
state: {
labelDataList: [], //存放打开的路由标签页
},
mutations: {
//打开新的页面的时候将页面的信息存到vuex里面
setLabelDataList(state, data) {
let boo = state.labelDataList.find((item) => {
return item.name == data.name;
});
if (!boo) {
state.labelDataList.push({
name: data.name,
path: data.path,
title: data.meta.title,
});
}
},
//当标签关闭的时候删除labelDataList 对应的数据
setDeleteLabelDataList(state, index) {
console.log(index);
state.labelDataList.splice(index, 1);
},
},
actions: {}, //通过mutations提交 可以是异步的
});
简单的业务实现
- 在需要的地方加入keep-alive标签,如下:
<router-view v-slot="{ Component }"> <keep-alive :include="labelDataName"> 注意这里的key必须是唯一的 否则缓存会失效 这里也是vue2(不需要key) 与vue3的区别 <component :is="Component" :key="$route.name" /> </keep-alive> <component :is="Component" v-if="!labelDataName.includes($route.name)" /> </router-view>
setup() { const store = useStore(); let labelDataName = computed(() => { //从vuex中取出需要换成的标签名,利用keep-alive的includea api缓存我们需要缓存的页面 return store.state.labelDataList.map((e) => e.name); }); return { labelDataName, }; },
- 最后实现页面标签
<div class="label" v-for="(item, index) in labelDataList" :key="item.name"> <a> <router-link :to="item.path">{{ item.title }}</router-link> </a> <a class="delete" @click="close(item, index)" v-if="item.path != '/home'" >x</a > </div> import { useStore } from "vuex"; import { useRoute, useRouter } from "vue-router"; setup() { const store = useStore(); const route = useRoute(); const router = useRouter(); let labelDataList = computed(() => { return store.state.labelDataList; }); const close = (item, index) => { store.commit("setDeleteLabelDataList", index); if (route.path === item.path) { router.push("/home"); } }; return { labelDataList, close }; }