能,但必须满足三个硬性条件:组件用 customelements.define() 注册、属性名符合 html 命名规范(小写+短横线)、事件用 customevent 触发。

能,但必须满足三个硬性条件:组件用 customElements.define() 注册、属性名符合 HTML 命名规范(小写+短横线)、事件用 CustomEvent 触发。缺一不可,否则在 React 或 Vue 里会丢状态或监听失效。
customElements.define() 必须在全局作用域提前执行
React/Vue 应用启动前,浏览器必须已注册该自定义元素。延迟注册(比如放在 React 组件的 useEffect 里)会导致首次渲染时标签被当作未知元素忽略,后续即使注册也需强制重渲染才能生效。
- 正确做法:把组件类定义和
customElements.define('my-input', MyInput)放在单独 JS 文件中,通过<script defer src="my-input.js"></script>加载,确保 DOM 解析完成前注册完毕 - Vue 中若用
v-html渲染自定义标签,不会触发connectedCallback—— 必须用真实 DOM 插入,不能字符串注入 - React 中若用
dangerouslySetInnerHTML同样无效;必须用 JSX 直接写<my-input value="test"></my-input>
attributeChangedCallback 只响应字符串属性
HTML 属性天然是字符串,attributeChangedCallback 拿到的 newValue 永远是字符串。React 传 value={123} 实际生成的是 value="123",组件内部必须手动转类型,否则 === 判断会失败。
- 常见错误:在
attributeChangedCallback里直接用if (newValue === true)—— 永远不成立,因为newValue是"true" - 建议统一处理逻辑:在
observedAttributes列表里声明的每个属性,都在回调里做类型转换,例如parseInt(newValue)或JSON.parse(newValue)(需包裹try/catch) - 布尔属性(如
disabled)要靠this.hasAttribute('disabled')判断,而非读取属性值
跨框架事件通信必须用 CustomEvent
React 的 onChange、Vue 的 @input 都无法监听原生自定义元素抛出的普通事件(如 new Event('change')),只有 CustomEvent 被标准支持。
- 错误写法:
this.dispatchEvent(new Event('change'))—— Vue/React 不会响应 - 正确写法:
this.dispatchEvent(new CustomEvent('change', { detail: { value: this.value } })) - React 中需用
onChange绑定,但实际监听的是原生change事件,所以必须确保事件名与 React 内置事件名一致(如change、input),否则要用addEventListener手动绑定 - Vue 中推荐用
v-on:change.native,避免被 Vue 的事件系统过滤掉
Shadow DOM 的样式隔离是默认生效的,但很多人忽略了一点:如果组件内部用 :host-context() 或 ::slotted 主动穿透宿主样式,就可能在不同框架下表现不一致 —— 尤其当框架自身注入了全局 CSS 时。这类细节不报错,但会让组件在某个框架里看起来“怪怪的”,排查起来最耗时间。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











