vue3获取组件名,自定义缓存组件,自定义清除缓存组件

目录

1、定义获取组件名的工具函数

2、使用

3、完整案例


 想要获取组件名,无非是要做自定义缓存组件和自定义清除缓存组件,或者是动态切换组件

但大概率都是缓存组件

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 没有内容,并且没有自定义组件name,就会返回 undefined
    console.log('componentName',componentName);
    
    return componentName
}

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>

猜你喜欢

转载自blog.csdn.net/weixin_59916662/article/details/129611803