前言
目前工作还是以 Vue2
为主,今早有人提问 如何动态挂载组件?
话说很久很久以前就实现过,今天再详细的整理一下此问题!
开始
动态组件如下,是个简单的例子:
- 但请注意这里给了个
id="test2"
; - 可传入
props
参数name
;
// 文件名 AComponents.vue
<template>
<h1 id="test2">这是 A 组件.{{name}}</h1>
</template>
<script>
export default {
props: {
name: {
type: String,
default: ''
}
}
}
</script>
重点来了:
- 方法
addNode
创建节点; - 方法
extendComponent
挂载组件,使用 全局 API Vue.extend 和 实例方法vm.$mount ; - 方法
destoryComponent
销毁组件,注意是寻找id
为test2
,因为test
已被替换;
<template>
<div class="extend-main">
<button @click="addNode">创建节点</button>
<button @click="extendComponent">挂载组件</button>
<button @click="destoryComponent">销毁组件</button>
</div>
</template>
<script>
import Vue from 'vue'
import AComponents from './../components/AComponents.vue'
export default {
methods: {
// 创建节点
addNode() {
// body 最后创建一个 id 为 test 节点
const divEl = document.createElement('div');
divEl.id = 'test';
document.body.appendChild(divEl);
},
// 挂载组件
extendComponent() {
// 使用基础 Vue 构造器,创建一个“子类”
const AComponentsEx = Vue.extend(AComponents);
// 创建实例,并挂载到指定 id 上
const aComponents = new AComponentsEx().$mount('#test');
// 可传入 props 值
aComponents.$props.name = '这是一个测试!';
},
// 销毁组件
destoryComponent() {
// 注意此时没有 id 为 test 的节点,已被 id test2 替换
const testEl = document.getElementById('test2');
document.body.removeChild(testEl);
}
}
}
</script>
效果
点击按钮 创建节点,body 新增 div。
点击按钮 挂载组件,新组件已替换。
点击按钮 销毁组件,div 被删除。
最后
2024年
是 Vue3
的时代!上述的挂载组件,Vue2
和 Vue3
是有差异的:
Vue2
被渲染的内容会替换我们要挂载的目标元素;Vue3
被渲染的应用会作为子元素插入,从而替换目标元素的 innerHTML。- 详见《Vue 3 迁移指南 - Mount API 的变化》