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

回到顶部