最常用继承写法是自定义类直接 extends HTMLElement 并用 customElements.define() 注册;constructor 中必须调用 super(),且适合初始化状态、创建 shadow root;需用 observedAttributes 与 attributeChangedCallback 响应属性变化;connectedCallback 用于 DOM 插入后操作,disconnectedCallback 清理副作用;attachShadow({mode: 'open'}) 实现样式与结构隔离。
最常用继承写法就是让自定义类 直接 extends htmlelement,再配合 customelements.define() 注册——这是浏览器识别并启用组件的唯一合法路径,其他写法都不被支持。
必须从 constructor 调用 super()
这是硬性要求,不写会报错。super() 确保实例具备原生元素的基础能力(如属性访问、事件系统、DOM 方法等)。
- constructor 是初始化状态、创建 shadow root、设置默认属性的最佳位置
- 此时元素尚未挂载,不能操作
this.parentElement或调用getBoundingClientRect() - 避免在 constructor 里发请求、渲染复杂 DOM 或执行耗时计算
用 observedAttributes + attributeChangedCallback 响应属性
让组件像 <input disabled> 那样自动响应 HTML 属性变化,需要两步配合:
- 在类中声明静态 getter:
static get observedAttributes() { return ['disabled', 'label', 'size']; } - 实现回调:
attributeChangedCallback(name, oldValue, newValue),在里面更新内部按钮禁用状态、文本内容或样式 - 注意:布尔属性(如 disabled)的
newValue可能是null或空字符串,需按语义判断是否启用
靠生命周期钩子控制真实行为时机
constructor 只管“出生”,真正干活要等元素进入 DOM:
-
connectedCallback:元素插入文档时触发,适合绑定事件、启动动画、发起数据请求 -
disconnectedCallback:必须在这里清理副作用,比如移除事件监听、清除定时器、取消未完成的 fetch -
adoptedCallback:跨 iframe 移动时触发,日常开发中较少使用,但不可忽略
用 attachShadow 实现封装隔离
只继承 HTMLElement 还不够,结构和样式仍会和页面冲突。必须主动创建影子根:
- 推荐在 constructor 中调用:
this.attachShadow({ mode: 'open' }) -
mode: 'open'允许外部 JS 访问el.shadowRoot,方便调试和测试 - 把样式
<style></style>和结构一起注入 shadowRoot,确保完全隔离

















