You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue 2中Vue.extend创建组件实例的Vue 3等效实现方式咨询

Vue 2 编程式创建组件逻辑迁移 Vue 3 实现方案

核心差异说明

Vue 3 移除了 Vue 2 中的 Vue.extend API,同时原生组件实例不再提供 $on、$once、$off 事件相关方法,我们可以通过 createVNode + render 组合实现等效的动态组件创建逻辑,再手动补充事件方法的兼容即可满足需求。

完整等效实现代码

import { createVNode, render } from 'vue'
import MyComponent from './MyComponent.vue'

let instance
const propsData = {}

// 1. 创建组件虚拟节点,传入props参数
const vnode = createVNode(MyComponent, propsData)
// 2. 创建临时渲染容器
const container = document.createElement('div')
// 3. 渲染组件到容器
render(vnode, container)
// 4. 将组件真实DOM挂载到body下
document.body.appendChild(container.firstElementChild)
// 5. 获取完整组件实例
instance = vnode.component.proxy

// 兼容实现$on、$once、$off方法,挂载到实例上
const eventHandlerMap = new Map()
instance.$on = (eventName, handler) => {
  if (!eventHandlerMap.has(eventName)) {
    eventHandlerMap.set(eventName, [])
  }
  eventHandlerMap.get(eventName).push(handler)
}

instance.$once = (eventName, handler) => {
  const onceWrapHandler = (...args) => {
    handler.apply(this, args)
    instance.$off(eventName, onceWrapHandler)
  }
  instance.$on(eventName, onceWrapHandler)
}

instance.$off = (eventName, handler) => {
  if (!eventHandlerMap.has(eventName)) return
  const handlerList = eventHandlerMap.get(eventName)
  const targetIndex = handlerList.indexOf(handler)
  if (targetIndex > -1) {
    handlerList.splice(targetIndex, 1)
  }
}

console.log(
  instance.$on,
  instance.$once,
  instance.$mount
)

注意事项

  • 拿到的 instance 就是完整的组件实例,包含所有自定义的属性、方法和Vue官方提供的实例属性,和模板中正常渲染的组件实例完全一致。
  • 如果项目中已经引入了mitt等事件总线库,可以直接将总线实例的对应方法挂载到组件实例上,无需手动实现事件逻辑。
  • 需要销毁组件时调用 render(null, container) 即可触发完整的组件销毁生命周期,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Fabio Nogueira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 03:45:00