一.相关文档
- KeepAlive 官方文档
- Vue Router 文档
- Pinia 文档
二.需求
- 首页->列表 —不缓存列表
- 列表->详情 —缓存列表
- 详情->列表 — 恢复列表缓存
三.代码如下
1.定义pinia
export const useStore = defineStore('store', {
state: () => ({
cachedList: [] //缓存白名单,详细表述见最后【补充】
}),
actions: {
// 添加缓存
addCachedList(view) {
if (this.cachedList.includes(view.name)) return;
this.cachedList.push(view.name);
},
// 移除缓存
delCachedList(view) {
const index = this.cachedList.indexOf(view.name);
index > -1 && this.cachedList.splice(index, 1);
}
}
})
2.router meta定义
const router = createRouter({
history: createWebHashHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/index',
name: 'Index',
component: () => import('../views/index.vue')
},
{
path: '/list',
name: 'List',
meta: {
keepAlive: true //标识需要缓存的页面
},
component: () => import('../views/list.vue')
},
{
path: '/info',
name: 'Info',
component: () => import('../views/info.vue')
},
]
})
3.视图处理
<template>
<router-view v-slot="{ Component }">
<keep-alive :include="cachedList">
<component :is="Component" :key="$route.fullPath" />
</keep-alive>
</router-view>
</template>
<script setup>
import { computed, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useStore } from '@/stores/index';
let store = useStore();
let { addCachedList } = store;
let route = useRoute();
let cachedList = computed(() => store.cachedList);
// 监听路由变化
watch(
route,
(val) => {
const { name, meta: { keepAlive } } = val;
if (name && keepAlive) { // 自动添加到缓存数组
addCachedList(val);
}
},
{ immediate: true }
);
</script>
4.列表页逻辑
#list.vue
<script setup>
import { onBeforeRouteLeave } from 'vue-router';
import { useStore } from '@/stores/index';
let { delCachedViews } = useStore();
onBeforeRouteLeave((to, from, next) => {
const names = ['Info'];
if (!names.includes(to.name)) {
delCachedViews(from); //移除缓存
}
next();
});
</script>
补充:
但下面场景会生成一样的 name
,此时需要自定义 name
自定义name的方式
方式一:新增 script
标签
<script>
export default {
name: 'HomePage'
}
</script>
方式二: 利用unplugin-vue-define-options/vite
#安装
npm i unplugin-vue-define-options -D
#vite 配置
import DefineOptions from 'unplugin-vue-define-options/vite';
export default defineConfig({
...
plugins: [
...
DefineOptions(),
...
]
})
#组件内使用
<script setup>
defineOptions({
name: 'HomePage'
});
</script>
方式三:利用vite-plugin-vue-setup-extend
#安装
npm i vite-plugin-vue-setup-extend -D
#vite
import { defineConfig, Plugin } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
export default defineConfig({
plugins: [vue(), vueSetupExtend()],
})
#组件内使用
<template>
<div>hello world {{ a }}</div>
</template>
<script lang="ts" setup name="App">
const a = 1
</script>