自定义标签名必须含短横线且不能是原生名;customElements.define()须在标签解析前执行;class必须继承HTMLElement且constructor首行调super();attributeChangedCallback不触发初始属性值。

自定义标签名必须含短横线且不能是原生名
浏览器靠短横线(-)识别自定义元素,没它就直接报错:Failed to execute 'define' on 'CustomElementRegistry': The name "mybutton" is not a valid custom element name。
-
my-button✅ 合法:小写 + 至少一个短横线 + 非保留名 -
my_button❌ 不合法:下划线不被识别为分隔符 -
div、button、slot、html❌ 所有原生标签名和全局保留名均禁止注册 -
x-button✅ 语法合法,但语义模糊,建议用nav-menu、date-picker这类可读性强的命名
customElements.define() 必须在标签解析前执行
如果 <my-input></my-input> 已出现在 HTML 中,而 customElements.define() 还没跑完,浏览器会把它当 HTMLUnknownElement 处理——生命周期不触发、属性读不到、DOM 里空着也不报错。
- 最稳妥方式:
<script></script>放在所有自定义标签之前(不是底部) - 推荐方案:用
<script defer src="components.js"></script>,确保脚本在 DOM 构建完成但尚未解析自定义标签时执行 - 绝对避免:
window.onload或DOMContentLoaded里注册——太晚,无法补救
class 必须继承 HTMLElement 且 constructor 第一行 super()
漏掉 super() 或没继承 HTMLElement,注册时就会抛 NotSupportedError 或实例化时报 Failed to construct 'MyButton': Please use the 'new' operator。
- 正确写法:
class MyButton extends HTMLElement { constructor() { super(); ... } } - 想扩展原生按钮行为?得继承
HTMLButtonElement,并用<button is="my-button"></button>写法,不能直接写<my-button></my-button> -
constructor里只做初始化:调super()、this.attachShadow()、绑定私有字段或事件监听器 - 别在
constructor里读属性(this.getAttribute('label')返回null)或操作 DOM(this.innerHTML = ''会失败)
attributeChangedCallback 不处理初始属性值
即使你写了 static get observedAttributes() { return ['value']; } 并实现了 attributeChangedCallback,<my-input value="hello"></my-input> 中的 value="hello" 也不会触发该回调——它只响应后续 JS 修改或 DOM 操作带来的变更。
立即学习“前端免费学习笔记(深入)”;
- 初始值必须在
connectedCallback中手动读取:this.value = this.getAttribute('value') || '' - 若需同步属性与内部状态,建议在
connectedCallback初始化后,再显式调一次this.setAttribute('value', this.value)触发首次回调(视逻辑需要) - 注意:
attributeChangedCallback的oldValue在首次变更时是null,不是空字符串



















