vue3获取组件名,自定义缓存组件,自定义清除缓存组件
目录
想要获取组件名,无非是要做自定义缓存组件和自定义清除缓存组件,或者是动态切换组件
但大概率都是缓存组件
1、定义获取组件名的工具函数
import router from "@/routes"
export default function getComponentName() {
let currentMatched = router.currentRoute.value.matched
let currentComponent = currentMatched[currentMatched.length - 1].components!.default
let componentName = currentComponent.name || (currentComponent as { __name: string }).__name
// 如果组件内的 script 没有内容,就会返回 undefined
console.log('componentName',componentName);
return componentName
}
注意一点的是:
在 3.2.34 或以上的版本中,使用
<script setup>
的单文件组件会自动根据文件名生成对应的name
选项,如果不满足以上的要求需要自定义组件名,否则也会返回undefined
2、使用案例
我在这准备了index1 / 2/ 3 文件,
script 标签内一定要有内容,没有内容相当于静态页面,会返回undefined,而且也没有必要缓存,
下面这个是index1的,你可放到index2/3,并手动修改下,以免混乱
<template>
index1
<button @click="num++">页面1的num++</button>
<div >{{ num }}</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
let num = ref(0);
</script>
App.vue
为了不写多余的代码,我没有处理边缘问题,但核心的缓存组件已经做好了
<script setup lang="ts">
import router from "./routes";
import getComponentName from "./utils/getComponentName";
import { ref } from "vue";
// 不要缓存的页面
let includeName = ref<string[]>([]);
// 需要缓存的页面
let excludeName = ref<string[]>([]);
// tabs栏
let tabs = ref<{ path: string; name: string; componentName: string }[]>([]);
const goto = async (path: string, name: string) => {
// 跳转,路由是Promise,是异步的
await router.push(path);
// 获取组件名
let comName = getComponentName();
// 现在你有 路由路径 和 这个路由路径的组件名
let tab = {
path,
name,
componentName: comName,
};
// 判断是否有这个tab页面,是否都通过测试,如果是空数组则返回true
let flag = tabs.value.every((item: any) => {
return item.path !== path;
});
// 如果没有就添加新的tab标签
if (flag) tabs.value.push(tab);
// 是否有组件名(看1的注释) &&
// ! 需要缓存的里面是否有这个组件名 &&
// ! 不要缓存的是否有这个组件名
if (comName && !includeName.value.includes(comName) && !excludeName.value.includes(comName)) {
includeName.value.push(comName);
}
};
//关闭对应的tab标签
const tabRemove = (item: any) => {
// 获取该路由对应的组件名
let index = tabs.value.findIndex((v: any) => v.path === item.path);
// 清除缓存组件名
let componentName = tabs.value[index].componentName;
if (componentName) {
includeName.value.splice(includeName.value.indexOf(componentName), 1);
}
// 也把tabs里面的清除
tabs.value.splice(index, 1);
};
</script>
<template>
<div>
菜单栏
<ul>
<li @click="goto('/index1', '页面1')">
<span>去页面1</span>
</li>
<li @click="goto('/index2', '页面2')">
<span>去页面2</span>
</li>
<li @click="goto('/index3', '页面3')">
<span>去页面3</span>
</li>
</ul>
</div>
<div>
tab栏
<ul>
<li v-for="item in tabs">
<span @click="router.push(item.path)">{{ item.name }}</span>
<span @click="tabRemove(item)">X</span>
</li>
</ul>
</div>
<div>
页面:
<router-view v-slot="{ Component }">
<keep-alive :include="includeName">
<component :is="Component" />
</keep-alive>
</router-view>
</div>
</template>
<style lang="css" scoped>
li {
cursor: pointer;
}
</style>