vue3 ,用component:is实现tab选项卡内容动态切换,怎么配置缓存组件的主动移除?
在菜单组件选中事件代码中,通过 defineAsyncComponent
动态导入组件,并且不注册的情况下,赋值给 component 的 :is
绑定的属性,实现局部无组件注册的动态组件渲染。
要做 tab 切换动态管理,每个选项卡对应的内容都要缓存,哪怕是同一个控件,而且还是带关闭按钮的那一种 tab 切换管理。点击关闭按钮移除选项卡对应动态组件的缓存(keep-alive
)。在关闭选项卡后,如何移除该选项卡显示的组件的缓存?
如果不是依赖全局动态注册组件,也就是基于 app.component(key,defineAsyncComponent(() => import('@/views/xxx.vue')))
这种形式,能做到吗?怎么做?
按照下面的代码,应该还要加点什么配置?
相关的vue组件代码
<template> <div class="box">
<div class="content5">
<div class="aside" >
<el-menu
class="el-menu-vertical-demo">
<template v-for="(item) in menuItems">
<el-menu-item :index="item.key" @click="menuClick(item)" >{{item.label}}</el-menu-item>
</template>
</el-menu>
</div>
<div class="tabs">
<div class="tabHeader">
<div>
<el-tabs v-model="current_content.activeName" @tab-click="tabHeaderClick" @tab-remove="removeTab" >
<el-tab-pane v-for="(item) in tab_list" :label="item.label" :name="item.code" :key="item.code" closable >
</el-tab-pane>
</el-tabs>
</div>
</div>
<div class="tabContent">
<keep-alive >
<component :is="current_content.view" ></component>
</keep-alive>
</div>
</div>
</div>
</div>
</template>
<script setup>
import {ref,reactive,defineAsyncComponent } from "vue"
//左侧菜单
let menuItems=reactive([]);
//tab导航
let tab_list=reactive([])
let current_content=reactive({
seq:1,
view_name:undefined,
view:undefined,
activeName:undefined,
});
// let currentContent=ref(undefined);
const menuClick=(menu)=>{
addTab(menu.label,menu.key,menu.view);
switchChildPage2(menu.key,menu.view);
}
const switchChildPage2=(key,view)=>{
if(key==current_content.view_name){
return;
}
current_content.view_name=key;
current_content.view=view;
current_content.activeName=key;
};
const addTab=(title,key,view)=>{
var item = tab_list.find((item) => item.code === key);
if(item!=null){
return;
}
var addTabItem={label:title,code:key,view:view}
tab_list.push(addTabItem);
}
const removeTab=(val)=>{
var index = tab_list.findIndex((item) => item.code === val);
if(index==-1){
return;
}
current_content.view_name=undefined;
current_content.view=undefined;
current_content.activeName=undefined;
tab_list.splice(index, 1);
if(tab_list.length!=0){
var fisrt=tab_list[0];
current_content.view_name=fisrt.key;
current_content.view=fisrt.view;
current_content.activeName=fisrt.key;
}
};
const tabHeaderClick=(val)=>{
var item = tab_list.find((item) => item.code === val.props.name);
switchChildPage2(item.code,item.view);
};
const load=()=>{
//测试动态获取菜单
var test1=[
{
title:"测试1",
component: defineAsyncComponent(()=>import('@/views/admin/test/test1.vue')),
},
{
title:"测试2",
component: defineAsyncComponent(()=>import('@/views/admin/test/test2.vue')),
},
];
//添加左侧菜单
for(var item2 of test1){
var menu={
label:item2.title,
key:'a'+current_content.seq,
view:item2.component,
};
current_content.seq++;
menuItems.push(menu);
}
}
load();
</script>
回答:
使用 keep-alive 的include,切换到tab时,将组件name添加到include,关闭tab时,将组件name移除
app.vue
<template> <div>
<el-menu class="el-menu-vertical-demo" :default-active="curTab">
<template v-for="(item, index) in menus">
<el-menu-item :index="item.title" @click="onMenuClick(item)">
{{item.title}}
</el-menu-item>
</template>
</el-menu>
<el-tabs v-model="curTab" @tab-click="onTabClick" @tab-remove="removeTab">
<el-tab-pane v-for="item in tabs" :label="item.title" :name="item.title" :key="item.title" closable>
</el-tab-pane>
</el-tabs>
<keep-alive :include="caches">
<component :is="curTabComp"></component>
</keep-alive>
{{ caches }}
</div>
</template>
<script setup>
import {ref, defineAsyncComponent, shallowRef, markRaw, nextTick, h, defineComponent } from "vue"
function lazy (name, source) {
return defineComponent({
name,
render: () => h(defineAsyncComponent(source))
})
}
const menus = ref([
{
title:"测试1",
component: markRaw(lazy('test1', ()=>import('./test/test1.vue'))),
name: 'test1'
},
{
title: "测试2",
component: markRaw(lazy('test2', ()=>import('./test/test2.vue'))),
name: 'test2'
},
{
title: "测试3",
component: markRaw(lazy('test3', ()=>import('./test/test3.vue'))),
name: 'test3'
}
])
const tabs = ref([])
const curTab = ref('')
const curTabComp = shallowRef()
const caches = ref([])
function onMenuClick (tab) {
if (!tabs.value.includes(tab)) tabs.value.push(tab)
if (!caches.value.includes(tab.name)) caches.value.push(tab.name)
nextTick(() => {
curTabComp.value = tab.component
curTab.value = tab.title
})
}
function onTabClick ({paneName}) {
const tab = Array.from(tabs.value).find(item => item.title === paneName)
if (tab) {
curTabComp.value = tab.component
curTab.value = tab.title
}
}
function removeTab (paneName) {
const tab = tabs.value.find(item => item.title === paneName)
if (tab) {
caches.value = caches.value.filter(item => item !== tab.name)
}
tabs.value = tabs.value.filter(item => item.title !== paneName)
const first = tabs.value[0]
curTabComp.value = first?.component
curTab.value = first?.title
}
</script>
<style lang='less' scoped>
</style>
下面是:test1.vue
<template> <div>
组件1 <br> {{ new Date().toLocaleTimeString() }}
</div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
onMounted(() => {
console.log('test1 mounted')
})
</script>
<style lang='less' scoped>
</style>
test2.vue
<template> <div>组件2 <br> {{ new Date().toLocaleTimeString() }}</div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
onMounted(() => {
console.log('test2 mounted')
})
</script>
<style lang='less' scoped>
</style>
以上是 vue3 ,用component:is实现tab选项卡内容动态切换,怎么配置缓存组件的主动移除? 的全部内容, 来源链接: utcz.com/p/933734.html