vue3 KeepAlive实操

75 阅读1分钟
一.相关文档
二.需求
  1. 首页->列表 —不缓存列表
  2. 列表->详情 —缓存列表
  3. 详情->列表 — 恢复列表缓存
三.代码如下
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>