web component 按钮仅适用于跨框架统一、样式隔离或内置国际化场景,常规用 class 按钮即可;自定义元素名必须含短横线且全小写,如 'wc-button';dom 操作和事件绑定须在 connectedcallback 中进行;需手动同步 disabled/type/name/value 等原生属性并代理 focus/click 方法;attributechangedcallback 仅响应 setattribute 等 dom 属性变更,且 observedattributes 必须全小写声明。

别用 Web Component 写按钮——除非你明确需要跨 React/Vue/纯 HTML 统一使用、强制样式隔离、或内置国际化逻辑。绝大多数场景下,<button class="btn-primary"></button> + CSS 就够了,更轻、更稳、更易调试。
自定义元素名必须带短横线,否则 customElements.define() 直接报错
浏览器强制校验命名规则,不是可选项。写成 mybutton、MyButton 或 button-x(开头或结尾带短横线)都会失败,错误信息是:Failed to execute 'define' on 'CustomElementRegistry': The name "mybutton" is not a valid custom element name。
- ✅ 正确写法:
customElements.define('wc-button', WcButton) - ❌ 错误写法:
customElements.define('wcbutton', WcButton)(缺短横线) - ❌ 错误写法:
customElements.define('wc-button-', WcButton)(结尾短横线非法) - 大小写不敏感,但惯例全小写 + 连字符,比如
data-submit-button,别写DataSubmitButton
connectedCallback 才是渲染和初始化的唯一安全时机
constructor 里调用 this.attachShadow({mode: 'open'}) 可以,但不能紧接着操作 this.shadowRoot —— 此时 DOM 尚未挂载,shadowRoot 可能为空或被静默丢弃,尤其在 SSR 或框架嵌套中极不稳定。
- 所有 DOM 操作(
innerHTML、appendChild、querySelector)必须放在connectedCallback中 - 事件监听也要在这里加,比如
this.button.addEventListener('click', ...) - 注意:
connectedCallback可能被多次触发(元素移出又插入),需自行防重或清理旧状态
必须手动同步 disabled、type、name、value,否则表单行为失效
Web Component 不会自动透传这些原生属性。如果只渲染一个内部 <button></button> 却不处理属性同步,会导致:表单提交时丢失 name/value、disabled 状态不响应、键盘焦点异常、屏幕阅读器识别失败。
-
disabled:要同步到内部<button></button>,并设tabindex="-1"和aria-disabled="true" -
type:只支持"button"、"submit"、"reset",且仅当父级是<form></form>时"submit"才有意义 -
name和value:必须显式赋值给内部<button></button>,否则表单序列化时不会包含 - 还要代理
focus()、click()方法,否则 JS 脚本调用会失败
attributeChangedCallback 不生效?检查 observedAttributes 和设置方式
这个回调只响应通过 setAttribute、removeAttribute 或 HTML 标签内声明(如 <wc-button disabled></wc-button>)触发的变更。JS 直接赋值 el.disabled = true 不会触发它。
- 必须显式声明:
static get observedAttributes() { return ['disabled', 'type', 'loading']; } - 属性名必须完全小写匹配,
'Disabled'或'DISABLED'都无效 - 首次渲染前在
constructor里设属性,connectedCallback之前不会触发回调 - 布尔属性如
loading,要写成el.setAttribute('loading', ''),而不是el.loading = true
真正难的不是写出来,而是让 <wc-button></wc-button> 在表单里 behave like a real <button></button>:submit 要触发、disabled 要禁用交互、键盘导航要进得去出得来、屏幕阅读器要读得准——这些细节漏掉任何一条,组件就只是个“长得像按钮”的壳子。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











