找回密码
 立即注册
首页 业界区 安全 Custom Elements 生命周期与 Lit 的映射关系详解 ...

Custom Elements 生命周期与 Lit 的映射关系详解

雨角 2 小时前
很多人在使用 Lit 时,会有一种“不太踏实”的感觉:
生命周期好像不多?
没有 beforeMount / mounted / beforeUpdate?
这真的够用吗?
原因在于:
Lit 并没有“发明生命周期”,
它只是忠实地站在 Custom Elements 之上。

本文将从 浏览器原生生命周期 出发,解释:

  • Custom Elements 提供了什么
  • Lit 在这些生命周期上做了哪些封装
  • Lit 的生命周期为什么这么“少”
  • 与 Vue / React 生命周期的本质差异
一、先给结论(Very Important)

Lit 的生命周期不是“简化版 Vue”,
而是“Custom Elements 生命周期 + 更新阶段钩子”。
理解这一点,后面一切都会顺。
二、Custom Elements 的原生生命周期

Web Components(Custom Elements)规范只定义了 4 个生命周期回调
  1. class MyElement extends HTMLElement {
  2.   constructor() {}
  3.   connectedCallback() {}
  4.   disconnectedCallback() {}
  5.   attributeChangedCallback() {}
  6. }
复制代码
就这么多,没有多余概念。
2.1 constructor


  • 元素被创建
  • 尚未插入 DOM
  • 不应该访问 DOM / attributes
  1. constructor() {
  2.   super()
  3. }
复制代码
2.2 connectedCallback


  • 元素被插入文档
  • 可以访问 DOM
  • 可能被多次调用(移动节点)
  1. connectedCallback() {
  2.   console.log('attached')
  3. }
复制代码
2.3 disconnectedCallback


  • 元素从文档移除
  • 用于清理副作用
  1. disconnectedCallback() {
  2.   console.log('detached')
  3. }
复制代码
2.4 attributeChangedCallback


  • 监听 attribute 变化
  • 必须显式声明 observedAttributes
三、Lit 是如何“站在”这些生命周期之上的

Lit 并没有绕过这些生命周期,而是:
在 Custom Elements 生命周期中插入“更新流程”
3.1 LitElement 的基本结构
  1. class LitElement extends ReactiveElement {
  2.   render() {}
  3. }
复制代码
真正的魔法发生在 ReactiveElement 中。
四、Lit 的完整生命周期执行顺序(重点)

当一个 Lit 组件被使用时,实际执行顺序是:
  1. constructor
  2.   ↓
  3. connectedCallback
  4.   ↓
  5. 第一次 requestUpdate
  6.   ↓
  7. shouldUpdate
  8.   ↓
  9. willUpdate
  10.   ↓
  11. render
  12.   ↓
  13. updated
复制代码
这是真正需要理解的生命周期链
五、Lit 生命周期逐个拆解

5.1 constructor
  1. constructor() {
  2.   super()
  3. }
复制代码
特点:

  • 不能访问 DOM
  • 不要在这里做副作用
  • 不要 set 响应式属性(会触发更新)
5.2 connectedCallback
  1. connectedCallback() {
  2.   super.connectedCallback()
  3. }
复制代码
用途:

  • 启动副作用(事件监听、observer)
  • 定时器
  • 与外部系统建立连接
注意:
connectedCallback ≠ mounted
它可能被调用多次。
5.3 requestUpdate(隐式生命周期)

Lit 中没有显式的 beforeMount,
requestUpdate 实际上就是更新的起点
  1. this.requestUpdate()
复制代码
5.4 shouldUpdate
  1. shouldUpdate(changedProps) {
  2.   return true
  3. }
复制代码
这是 Lit 给你的唯一更新拦截点

  • 返回 false → 跳过整个更新流程
  • 非常适合做性能控制
5.5 willUpdate
  1. willUpdate(changedProps) {}
复制代码
用途:

  • 基于属性变化,派生内部状态
  • 类似 Vue 的 watch + computed
不要在这里操作 DOM
5.6 render(核心)
  1. render() {
  2.   return html`...`
  3. }
复制代码
特点:

  • 每次更新都会执行
  • 必须是纯函数
  • 不应该产生副作用
5.7 updated
  1. updated(changedProps) {}
复制代码
用途:

  • DOM 已经更新完成
  • 安全操作 DOM
  • 类似 Vue 的 updated / mounted
5.8 disconnectedCallback
  1. disconnectedCallback() {
  2.   super.disconnectedCallback()
  3. }
复制代码
用途:

  • 清理副作用
  • 取消事件 / observer / timer
六、Lit 生命周期为什么“这么少”?

这是一个设计结果,不是能力不足。
6.1 Lit 把生命周期拆成两类


  • 元素生命周期(来自浏览器)
  • 更新生命周期(围绕 render)
而不是像 Vue 那样混合在一起。
6.2 对比 Vue 生命周期

VueLitbeforeCreateconstructormountedfirstUpdated / updatedbeforeUpdateshouldUpdateupdatedupdatedunmounteddisconnectedCallbackLit 的生命周期不是少,而是更贴近底层模型
七、一个非常容易踩的坑(Important)

错误认知

“connectedCallback 只会执行一次”
正确认知

只要元素被移除再插入,就会再次执行
因此:

  • 不要在这里假设“只初始化一次”
  • 真正的一次性逻辑可以放在 firstUpdated
八、firstUpdated:Lit 的“妥协点”
  1. firstUpdated() {
  2.   // 只执行一次
  3. }
复制代码
这是 Lit 提供的唯一一个非原生生命周期,目的只有一个:
满足开发者对“mounted once”的直觉需求
九、为什么 Lit 不提供更多生命周期?

因为:

  • 生命周期越多,心智负担越重
  • 浏览器模型已经足够清晰
  • 多余的钩子会掩盖真实执行顺序
Lit 的选择是:
让开发者面对真实模型,而不是被抽象包裹
十、在工程实践中的建议(IIImportant)

10.1 推荐的使用方式

场景生命周期初始化状态constructor启动副作用connectedCallback派生状态willUpdateDOM 操作updated / firstUpdated清理资源disconnectedCallback十一、一个核心结论(Remember)

Lit 的生命周期不是“不够用”,
而是“不替你做决定”。
它把控制权交还给:

  • JavaScript
  • 浏览器
  • 架构设计者

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册