组件的动态注册还是比较容易的,使用<component :is="组件id"></component>即可,但动态卸载有难度,相关文献较少。不过,如果巧妙使用vnode,就能轻松实现!
下图展示了4个代表不同文档材料的Vue组件。为简化起见,每个组件用一个DIV元素表示,其内容为一张图片。只要双击某个图片,即可卸载该图片对应的Vue组件!
组件被删除前
组件被删除后
1 编写html文件
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>组件的动态注册和卸载</title>
<style>
.menu-docs {
position: absolute;
width: 450px;
height: 360px;
font-size: 16px;
text-align: center;
top: 10px;
padding: 2px;
border: 1px solid #F00;
background: rgba(236, 223, 223, 0.2);
box-shadow: 2px 2px 2px #ccc;
}
</style>
<script type="importmap">
{
"imports": {
"vue": "./js/vue.esm-browser.prod.js"
}
}
</script>
</head>
<body>
<div class="menu-docs" id="app"></div>
<script type="module">
import {createApp} from 'vue'
import {AuthorDocs} from "./js/uninstall.js"
createApp(AuthorDocs).mount('#app')
</script>
</body>
</html>
2 编写js/uninstall.js
组件的卸载,关键点是需要做两件事情:(1)从页面元素集合中移除当前待删除元素;(2)删除当前Vue实例中的对应组件。
import {defineAsyncComponent, defineComponent, getCurrentInstance, h} from 'vue'
export const AuthorDocs = defineComponent({
setup() {
const docs = [ //组件的id及图片内容
{id: 'computerApp', image: 'image/computerapp.jpg'},
{id: 'computerGc', image: 'image/computergc.jpg'},
{id: 'rcp', image: 'image/rcp.jpg'},
{id: 'spring', image: 'image/spring.png'}
]
const instance = getCurrentInstance() //应用实例
const app = instance.appContext.app //应用相关数据
docs.forEach(({id, image}, index) =>
app.component(id, h(asyncComponent, { //h函数渲染
instance: instance, //当前Vue应用
id: id, //材料的id号
image: image //材料对应图片URL
}))
)
return {docs}
},
template: `
<div>
<template v-for="(doc,index) in docs">
<component :is="doc.id"></component> <!--动态加载组件-->
</template>
</div>
`
})
const asyncComponent = defineAsyncComponent( //异步组件
() => Promise.resolve({
props: {
instance: Object,
id: String,
image: String
},
setup({instance, id, image}) {
const delDocs = (id) => {
const vnode = instance.vnode //获取虚拟元素结点
const children = vnode.el.children //获得元素集合:div层
const appComponents = vnode.appContext.components //拿到组件集合
Object.keys(appComponents)
//过滤出computerApp、computerGc、rcp、spring这4个组件
.filter(key => appComponents[key].__v_isVNode)
.forEach((key, index) => {
if (key === id) { //是当前双击的组件
children[index].remove() //移除当前div层元素
//删除当前Vue应用中,组件集合中的对应组件
delete appComponents[key]
}
})
}
return {id, image, delDocs}
},
template: `
<div style="float:left;padding:0 20px 10px 2px;">
<img :src="image" width="200" height="170"
@dblclick="delDocs(id)" title="双击删除">
</div>
`
})
)
标签:Vue,const,image,js,instance,卸载,组件,id,加载
From: https://blog.csdn.net/acoease/article/details/143406588