无需登录 数据私有 本地保存

Web Component 生命周期演示 - 自定义元素钩子调用

10
0
0
0

Web Component 生命周期演示

直观展示自定义元素的五个生命周期钩子调用时机与顺序

0
constructor
0
connected
0
disconnected
0
adopted
0
attributeChanged
📄 主文档 (Main Document)
元素将显示在这里
🖼️ iframe 文档 用于演示 adoptedCallback
元素状态: 未创建 未连接
生命周期调用日志
共 0 条记录
点击上方按钮开始演示,日志将实时显示在这里
常见问题与知识点

Web Component(自定义元素)共有 5个 生命周期钩子:

  • constructor() — 元素实例化时调用,用于初始化状态、创建Shadow DOM。不能操作DOM属性或子元素。
  • connectedCallback() — 元素被插入到文档DOM时调用,适合执行DOM相关初始化、获取数据、设置事件监听。
  • disconnectedCallback() — 元素从文档DOM移除时调用,适合清理资源、移除事件监听、取消定时器。
  • adoptedCallback(oldDoc, newDoc) — 元素通过 document.adoptNode() 移动到新文档时调用。
  • attributeChangedCallback(name, oldVal, newVal) — 监听的属性发生变化时调用,需配合 static observedAttributes 使用。

constructor 在元素创建时立即调用(newdocument.createElement),此时元素尚未连接到DOM,无法访问父节点、子元素或属性。适合创建Shadow DOM和初始化内部状态。

connectedCallback 在元素实际插入到文档DOM后才调用,此时可以安全地访问DOM树、获取属性值、发起网络请求、设置事件监听器。元素可能被多次移除和重新插入,每次插入都会触发此回调。

简单记忆:constructor = 出生证明,connectedCallback = 正式上岗。

只有当属性名被列在 static observedAttributes 数组中时,该属性的变化才会触发 attributeChangedCallback

static get observedAttributes() {
    return ['label', 'color']; // 只有这两个属性变化会触发回调
}

触发方式包括:setAttribute()removeAttribute()、直接修改HTML属性。注意:通过JavaScript属性赋值(如 el.label = 'x')不会自动触发,需在setter中手动调用 setAttribute

adoptedCallback 在日常开发中较少使用,但在以下场景中很有价值:

  • 元素在iframe之间移动时(跨文档迁移)
  • 使用 document.adoptNode() 将元素从一个文档转移到另一个文档
  • HTML模板系统前端微服务架构中,组件可能在不同文档上下文间迁移

回调接收两个参数:adoptedCallback(oldDocument, newDocument),可用于重新绑定文档相关资源。

正常创建并添加到DOM:

  1. constructor() — 元素实例化
  2. connectedCallback() — 元素插入DOM
  3. attributeChangedCallback() — 如果有属性在connected之前或之后被设置

跨文档移动(adoptNode):

  1. disconnectedCallback() — 从原文档DOM移除
  2. adoptedCallback() — 文档归属变更
  3. connectedCallback() — 添加到新文档DOM(如果执行了appendChild)

移除再重新添加:disconnectedCallback → connectedCallback(可多次循环)

  • constructor中只做轻量初始化 — 创建Shadow DOM、初始化默认状态,避免操作DOM属性。
  • 在connectedCallback中获取属性 — 此时元素已在DOM中,属性可安全读取。
  • 在disconnectedCallback中清理资源 — 移除事件监听、取消定时器、断开Observer,防止内存泄漏。
  • 使用observedAttributes声明监听属性 — 精确控制哪些属性变化需要响应。
  • 使用Shadow DOM封装样式 — 避免外部CSS影响组件内部,保持隔离性。
  • 考虑SSR兼容性 — 在服务端渲染环境中,部分生命周期钩子可能表现不同。