web components 必须遵守硬性规则:自定义标签名含连字符且非原生名;constructor 仅初始化,dom 操作须在 connectedcallback 中进行;shadow dom 样式需显式注入;attributechangedcallback 不触发初始值,需在 connectedcallback 手动同步。

自定义标签注册失败、样式不生效、属性没反应,不是浏览器不支持,而是没踩对 Web Components 的几个硬性规则。
自定义标签名必须含连字符且不能是原生名
浏览器靠连字符(-)区分原生标签和自定义标签。像 mybutton 或 MyButton 会直接报错:Failed to execute 'define' on 'CustomElementRegistry': The name "mybutton" is not a valid custom element name。
-
my-button✅ 合法(小写 + 连字符 + 非保留名) -
my_button❌ 下划线不被识别 -
div、slot、html❌ 所有原生标签名及全局保留名均禁止注册 -
x-button✅ 技术上可行,但语义模糊,建议用date-picker、nav-menu这类可读性强的命名
constructor 只能初始化,DOM 操作必须等 connectedCallback
在 constructor 里写 this.innerHTML = '' 或调 this.getAttribute('value'),轻则属性读不到,重则触发 NotSupportedError: Failed to execute 'attachShadow'。
- ✅ 允许做的事:调
super()、this.attachShadow({ mode: 'open' })、初始化私有字段、绑定事件监听器(但别操作 DOM) - ✅ 必须等
connectedCallback触发后,才能读属性、渲染模板、appendChild 子节点 - ⚠️ 注意:
connectedCallback可能被多次调用(如元素被移出又重新插入 DOM),逻辑需幂等
Shadow DOM 隔离样式,外部 CSS 不穿透,内部样式不泄漏
写了 this.attachShadow({ mode: 'open' }) 却发现字体、颜色全丢了?不是 bug,是 Shadow DOM 天然隔离。
- ❌
<style>body { color: red }</style>在 shadow 内无效 ——body根本不存在于 shadow 中 - ✅ 必须显式注入样式:
shadowRoot.innerHTML = '<style>:host { display: inline-block; } .label { font-weight: bold; }</style> <span class="label"></span>' - ✅ 想让外部控制尺寸或主题色?用 CSS 自定义属性:
:host([size="large"]) { font-size: 1.2em; },再配合get attributeStyleMap()或style.setProperty('--theme-color', ...)
attributeChangedCallback 不触发初始值,需手动同步
HTML 中写 <my-input value="hello"></my-input>,但 attributeChangedCallback 一次都不调 —— 这是设计行为,不是 bug。
- ✅ 必须在
connectedCallback里手动读取初始属性:this.value = this.getAttribute('value') || '' - ✅
static get observedAttributes()返回数组必须精确匹配属性名(大小写敏感),比如['value', 'disabled'],漏写就监听不到 - ⚠️ 注意:布尔属性(如
disabled)在 HTML 中写成<my-input disabled></my-input>时,其值为""而非"true",判断时别用=== true
最常被忽略的点是:初始属性同步和 connectedCallback 的幂等性。很多人只测“首次加载”,一动 DOM 就出问题 —— 真实场景里,元素很可能被反复挂载/卸载。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











