自定义元素注册失败、属性不响应、样式失效,主要卡在constructor时机、observedAttributes声明、连字符命名三处:constructor必须调super()并立即attachShadow();需声明static get observedAttributes()才能触发attributeChangedCallback;标签名必须含且仅含一个连字符。
自定义元素能直接用原生 Web Components 实现,无需框架;但注册失败、属性不响应、样式失效,基本都卡在 constructor 时机、observedAttributes 声明、连字符命名这三处。
浏览器只允许在 constructor 中首次调用 this.attachShadow()。如果拖到 connectedCallback 再执行,HTML 解析器早已把子节点(比如文本、<slot>)塞进 light DOM,此时再 attach 就违反规范。
constructor 里只做三件事:调 super()、执行 this.attachShadow({ mode: 'open' })、初始化私有字段或默认属性constructor 里读 this.textContent 或写 this.innerHTML = ''——前者为空,后者污染 light DOMconnectedCallback 中执行HTML 属性变更不会自动同步到 JS 属性,也不会触发重绘。哪怕你写了 this.size = newValue,若没在类中声明 static get observedAttributes() 返回 ['size'],回调根本不会执行。
'disabled' ≠ 'Disabled',大小写敏感<my-button size="large"></my-button>),attributeChangedCallback 不会触发——得在 connectedCallback 里手动同步一次oldValue 和 newValue 永远是字符串,数值型需手动转:parseInt(newValue) 或 parseFloat(newValue)
Shadow DOM 天然隔离样式,<link rel="stylesheet"> 或全局 button { background: blue } 对 shadow 内部无影响。
立即学习“前端免费学习笔记(深入)”;
<style></style> 注入到 shadow,例如 shadow.innerHTML = '<style>button{background:blue}</style><button>OK</button>'
style 元素并 append:const style = document.createElement('style'); style.textContent = '...'; shadow.appendChild(style);
:host([theme="dark"]) { --bg-color: #333; },再在 shadow 内部用 var(--bg-color)
customElements.define() 要求第二个参数是合法的自定义标签名,规则硬性:必须包含且仅含一个连字符(-),不能以数字开头,不能是保留字(如 html、script、div)。
my-button ✅ 合法(小写、含单连字符、非保留名)my_button ❌ 下划线不被识别mybutton 或 MyButton ❌ 都会抛出 DOMException: Failed to execute 'define' on 'CustomElementRegistry': "mybutton" is not a valid custom element name
x-button ✅ 可用,但建议语义化,如 date-picker、nav-menu
最易被忽略的是初始属性同步和连字符命名——前者导致“HTML 里写了 value=123,JS 里却读不到”,后者让整个组件根本注册不上,连报错都看不到。这两个点不卡死,其他逻辑才可能跑起来。