当前位置:首页 > 文章列表 > 文章 > 前端 > 如何用继承创建自定义 DOM 元素

如何用继承创建自定义 DOM 元素

2026-05-20 16:27:33 0浏览 收藏
本文深入解析了如何通过继承 HTMLElement 类来创建真正符合 Web 标准的自定义 DOM 元素——这不是简单的功能叠加,而是深度复用浏览器原生元素的生命周期管理、属性响应机制与 DOM 行为能力;从强制调用 super() 的构造函数初始化,到通过 observedAttributes 与 attributeChangedCallback 精准响应属性变更,再到 connectedCallback、disconnectedCallback 等生命周期钩子实现高效资源管控,最后结合 attachShadow 构建隔离的 Shadow DOM 实现样式与结构的彻底封装,整套方案既严谨又实用,是构建可维护、高性能、强封装 Web 组件的核心路径。

如何利用 继承实现自定义 DOM 元素 (Web Components)

核心是继承 HTMLElement 类,再通过 customElements.define() 注册为新标签。这不是简单“加功能”,而是复用浏览器原生元素的生命周期、属性访问、DOM 行为等底层能力。

继承 HTMLElement 是必须步骤

所有自定义元素都必须以 class MyEl extends HTMLElement 开始。不继承就无法被浏览器识别为合法元素,customElements.define() 会报错。

  • constructor 中必须先调用 super(),这是强制要求
  • 可在构造函数里做初始化,比如创建 shadow root、设置默认状态,但此时元素尚未插入 DOM,不能操作父级或尺寸相关 API
  • 避免在 constructor 中执行耗时操作或依赖外部资源(如 fetch),会影响元素创建性能

用 observedAttributes + attributeChangedCallback 响应属性变化

原生元素(如 <input disabled>)能响应 HTML 属性变化,自定义元素也要做到这一点,靠的是静态 getter 和回调函数配合。

  • 在类中定义 static get observedAttributes() { return ['disabled', 'label', 'theme']; }
  • 实现 attributeChangedCallback(name, oldValue, newValue),在里面更新内部结构或样式
  • 注意:只有已声明在 observedAttributes 中的属性,修改才会触发该回调;布尔属性(如 disabled)值变化时,newValue 可能是 null 或字符串 "",需按语义处理

利用生命周期钩子控制行为时机

继承带来的不只是结构,还有标准的生命周期方法,它们对应元素在 DOM 中的真实状态。

  • connectedCallback:元素挂载到文档时触发,适合绑定事件、启动定时器、发起请求
  • disconnectedCallback:元素从文档移除时触发,必须在这里清理副作用(如 removeEventListener、clearTimeout)
  • adoptedCallback:元素被移动到另一个 document 时触发(少见,但跨 iframe 场景有用)
  • attributeChangedCallback 已在上一节说明,它和上述三个共同构成完整生命周期

结合 Shadow DOM 实现真正封装

仅继承 HTMLElement 还不够——样式和结构仍会与页面其他部分冲突。必须主动创建影子根来隔离。

  • constructorconnectedCallback 中调用 this.attachShadow({ mode: 'open' })
  • mode: 'open' 允许 JS 从外部访问 element.shadowRoot,方便测试和调试;'closed' 则完全隐藏,一般不推荐
  • 把结构写入 shadowRoot.innerHTML,或用 document.createElement 动态构建,再 append 进去
  • 内部样式用
    微信登录更方便
    • 密码登录
    • 注册账号
    登录即同意 用户协议隐私政策
    返回登录
    • 重置密码