使用 defineCustomElement 可将 Vue 组件转为原生自定义元素,核心三步:写组件、转元素、注册标签;生成继承 HTMLElement 的类,脱离 Vue 运行,支持跨框架使用。

直接用 defineCustomElement 把 Vue 组件变成浏览器原生支持的自定义元素,核心就三步:写组件、转元素、注册标签。它不是封装成 Vue 子组件,而是生成一个真正继承 HTMLElement 的类,能脱离 Vue 运行,也能在 React、纯 HTML 里直接用。
基础转换:从普通组件开始
你写的 Vue 组件(选项式或组合式)几乎不用改,只需用 defineCustomElement 包一层:
- props、emits、setup、template 都保持原样,和
defineComponent用法一致 - 不支持
<script setup>语法糖,必须显式导出默认对象(SFC 中建议用.ce.vue后缀标识) - 样式会自动注入到 Shadow DOM,避免污染全局,无需额外处理 scoped
注册并使用:像原生标签一样嵌入
转换后得到的是一个 Custom Element 构造函数,需手动注册到浏览器:
- 调用
customElements.define('my-editor', MyEditor),标签名必须含短横线(如my-editor) - 注册后可在任意 HTML 中直接写
<my-editor message="hello"></my-editor> - 属性绑定用小写横线格式(
user-id),对应组件 props 的驼峰名(userId)
在 Vue 应用中正确识别它
如果你在 Vue 项目里同时用这个自定义元素,Vue 默认会把它当 Vue 组件解析,导致警告。需告诉编译器“这是原生元素”:
立即学习“前端免费学习笔记(深入)”;
- Vite 项目:在
vite.config.ts的@vitejs/plugin-vue配置中加compilerOptions.isCustomElement: tag => tag.startsWith('my-') - Vue CLI:在
vue.config.js的vue-loader选项里设置同上 - 这样 Vue 就跳过组件解析,按标准 HTML 元素处理,支持 v-bind、@event 等语法
数据与事件:遵循 Web Components 规范
通信方式和原生元素对齐,不依赖 Vue 特有机制:
- props → 作为 HTML 属性传入,字符串值会自动转为 number/boolean(若声明了类型)
- 事件用
dispatchEvent(new CustomEvent('change', { detail })),外部监听element.addEventListener('change', ...) - 想响应 v-model,组件需 emit
'update:xxx',且定义props: { xxx: String }和emits: ['update:xxx']


















