Vue 3 如何实现编程式动态创建并挂载子组件?
Vue3 编程式动态创建挂载组件实现方案
Vue3移除了Vue2中的Vue.extendAPI,你可以通过以下两种方式实现同等功能:
方式一:createVNode + render(推荐,继承当前组件上下文)
该方案可以直接继承当前父组件的应用上下文,不需要手动注册store、i18n等插件,和你Vue2中的原有行为完全一致。
选项式API实现:
import { createVNode, render } from 'vue' import ChildComponent from './ChildComponent.vue' // ParentComponent.vue export default { methods: { createChild() { // 1. 创建子组件虚拟节点,传递props和事件 const childVNode = createVNode(ChildComponent, { // 直接写props参数,不需要用propsData字段 propA: '测试参数', propB: 123, // 自定义事件用on+驼峰命名绑定,比如@close对应onClose onClose: () => { // 组件销毁逻辑 render(null, container) document.body.removeChild(container) } }) // 2. 继承当前组件的应用上下文,$store、$i18n等插件能力自动生效 childVNode.appContext = this.$.appContext // 3. 创建挂载容器 const container = document.createElement('div') document.body.appendChild(container) // 4. 渲染挂载组件 render(childVNode, container) // 如需获取组件实例,可通过以下方式访问 const childInstance = childVNode.component.proxy } } }
组合式API实现:
import { getCurrentInstance, createVNode, render } from 'vue' import ChildComponent from './ChildComponent.vue' export default { setup() { const instance = getCurrentInstance() const createChild = () => { const childVNode = createVNode(ChildComponent, { propA: '测试参数', onClose: () => { render(null, container) document.body.removeChild(container) } }) childVNode.appContext = instance.appContext const container = document.createElement('div') document.body.appendChild(container) render(childVNode, container) } return { createChild } } }
方式二:createApp实现(独立上下文场景)
如果需要创建完全独立、不共享父组件上下文的组件实例,可以用该方案:
import { createApp } from 'vue' import ChildComponent from './ChildComponent.vue' import store from '@/store' import i18n from '@/i18n' export default { methods: { createChild() { const container = document.createElement('div') document.body.appendChild(container) // 创建独立app实例,手动注册需要的插件 const childApp = createApp(ChildComponent, { propA: '测试参数', onClose: () => { childApp.unmount() document.body.removeChild(container) } }) // 手动挂载需要的插件 childApp.use(store).use(i18n) // 挂载组件 childApp.mount(container) } } }
注意事项
- 组件使用完成后务必执行销毁逻辑,避免内存泄漏
- 如需传递插槽,可以在createVNode第三个参数传入插槽配置,示例:
const childVNode = createVNode(ChildComponent, { propA: 'xxx' }, { default: () => '默认插槽内容', header: () => h('div', '自定义头部') })
- 自定义事件绑定严格遵循
on+驼峰命名规则,比如事件名update:modelValue对应onUpdate:modelValue
内容的提问来源于stack exchange,提问作者srjjio
相关产品推荐
相关产品推荐

