Lit 3.x 演进全解析:从 CHANGELOG 看 Lit 库的核心能力与破坏性变更
2026/9/13 2:36:10 网站建设 项目流程

Lit 3.x 演进全解析:从 CHANGELOG 看 Lit 库的核心能力与破坏性变更

【免费下载链接】litLit is a simple library for building fast, lightweight web components.项目地址: https://gitcode.com/GitHub_Trending/li/lit

本篇技术指南以packages/lit/CHANGELOG.md为主体脉络,系统梳理 Lit 从 2.0 到 3.3 的完整演进历史。你将了解到:lit聚合包如何整合lit-htmllit-element@lit/reactive-element三大底层库;3.x 系列引入的useDefault属性选项、mathml模板标签、ref/choose/when等指令的行为变化;以及 IE11 支持移除、SSR 能力增强等关键里程碑。阅读本文后,你能准确判断每个版本特性背后的实现原理,并据此规划升级路径与迁移策略。

说明:CHANGELOG 中的全部条目均可在 packages/lit/CHANGELOG.md 中核对原文;文中涉及的源码路径均来自本仓库,可作为深入阅读的起点。

一、lit 聚合包与版本发布机制

1.1 什么是 lit 包

lit包是整个 Lit 生态的统一入口,它在2.0.0版本(CHANGELOG 对应条目)正式发布,将原先分散使用的LitElementReactiveElementlit-html整合到一个包中。从源码 packages/lit/src/index.ts 可以看到,它直接重导出了底层库的全部公开 API:

export * from 'lit-element/lit-element.js'; export * from 'lit-html/is-server.js';

同时在模块顶部预导入@lit/reactive-elementlit-html,以便在未打包(unbundled)加载时避免额外的请求瀑布(waterfall,见源码注释 index.ts)。

当前仓库中 lit 包的版本为3.3.3(见 packages/lit/package.json),其依赖关系也印证了聚合包的定位:

依赖包版本范围说明
@lit/reactive-element^2.1.0响应式属性、生命周期基座
lit-element^4.2.0基于 ReactiveElement 的组件基类
lit-html^3.3.0模板渲染引擎与指令体系

1.2 Changesets 自动化发布

CHANGELOG 末尾明确说明:3.0.0-rc.2之前的条目遵循 Keep a Changelog 格式人工维护,而此后(## 3.0.0-pre.0起的条目)全部由 Changesets 工具自动生成。这解释了为什么每个版本条目都带有 PR 编号、commit 哈希与贡献者致谢,格式高度统一。

二、Lit 3.x:现代化基线与大版本破坏性变更

3.0.0是 Lit 放弃旧浏览器支持、全面拥抱现代 Web 平台的里程碑。以下破坏性变更全部来自 CHANGELOG 3.0.0 小节:

2.1 放弃 IE11 支持

3.0.0正式移除了对 IE11 的支持(PR #3756)。这一决定使得 lit-html 可以简化属性处理逻辑:对符合标准的浏览器而言,属性按源码顺序迭代,因此 lit-html 简化了属性绑定处理(PR #3751);布尔属性部件改用toggleAttribute()实现(PR #3750);SVG 模板改用replaceWith()渲染(PR #3759)。这些简化意味着 Lit 3.x 的代码更精简、运行时开销更小,但也要求你的目标环境必须是现代浏览器。

2.2 响应式属性访问器自动请求更新

在 3.0.0 中,为响应式属性生成的访问器会自动包装用户自定义访问器,并在 setter 中自动调用this.requestUpdate()(PR #4146)。如果你仍需要完全掌控 setter 行为,可以设置noAccessor: true,此时必须自行在 setter 中调用this.requestUpdate()才能触发响应式更新。这是升级到 3.x 后最容易踩到的行为差异点之一。

2.3 移除实验性 hydrate 模块与废弃 API

  • 实验性 hydrate 模块(lit-html/experimental-hydrate.jslit-element/experimental-hydrate-support.js)从主包移除,迁移至@lit-labs/ssr-client(PR #3765)。实际上早在 2.7.1 中这些模块就已被标记废弃并移动(见 CHANGELOG 2.7.1),3.0.0 只是完成最终清理。
  • 删除queryAssignedNodes的废弃行为与参数(PR #3850)。旧写法@queryAssignedNodes('list', true, '.item')应迁移为:
@queryAssignedElements({slot: '', flatten: false, selector: '.item'})
  • ReactiveElement.renderRootcreateRenderRoot()的返回类型统一为HTMLElement | DocumentFragment,与 lit-html 的render()方法保持一致(PR #4254)。
  • PropertyValues.get()的返回类型加入undefined(PR #3710);移除 Lit 1 → Lit 2 的迁移警告(PR #3762)。

2.4 异步 performUpdate 警告与类型系统升级

3.0.0 对异步覆盖performUpdate()的情况发出警告(PR #3896),避免开发者无意中破坏更新调度。同时将 TypeScript 升级至 ~5.2.0(PR #4141),并确保装饰器在experimentalDecorators: true时也能与accessor关键字协同工作(PR #4183)。随 3.0.0 一同发布的还有依赖包的大版本升级:@lit/reactive-element@2.0.0lit-html@3.0.0lit-element@4.0.0(见 CHANGELOG 依赖更新节)。

三、Lit 3.x 新增能力:useDefault 与 mathml

3.1useDefault属性选项(3.3.0)

3.3.0为响应式属性新增了useDefault选项(PR #4934),其行为在 reactive-element.ts 中有明确实现:

当设置useDefault: true时,初始默认值不会被当作一次"变更",因此当同时设置reflect: true时,初始值不会反射到 DOM 属性;此外,当属性(attribute)被移除时,会恢复默认值

源码层面,ReactiveElement 通过__defaultValuesMap 记录默认值(reactive-element.ts),并在属性变化判定中加入角力条件:当useDefault && reflect且新值等于默认值、而对应 attribute 尚未设置时,也视为一次变更(以触发反射)。useDefault的默认值为false(见 defaultPropertyDeclaration)。

@property({reflect: true, useDefault: true}) count = 0; // 初始 0 不会反射为 count="0";移除 count 属性后恢复为 0

从源码注释(reactive-element.ts)可知:大多数需要反射到 attribute 的属性都建议使用useDefault: true,以避免初始值被意外反射。注意使用该选项时属性必须被初始化(字段初始化器或构造函数赋值均可)。

3.2mathml模板标签(3.2.0)

3.2.0新增了 MathML 支持,引入mathml模板标签(PR #4637)。在 lit-html.ts 中,htmlsvgmathml三个标签函数并列定义,均基于各自的 result type(HTML_RESULTSVG_RESULTMATHML_RESULT)创建模板结果:

import {html, svg, mathml} from 'lit'; // 在 HTML 中嵌入 MathML 片段 render(mathml`<math><mi>x</mi></math>`, container);

从源码结构看,mathmlsvg定位类似,用于渲染独立命名空间下的标记片段。3.2.0 同时将 lit-html 升级至 3.2.0、lit-element 升级至 4.1.0(见 CHANGELOG 3.2.0)。

3.3 3.3.x 的其他修复

  • 3.3.3ref指令在其内部 ref 为undefined时也能优雅断开(PR #5218)。
  • 3.3.2ClassInfo变为可修改(PR #5044);修复带装饰器的标准私有访问器在变更检测中的 Bug(PR #4999)。
  • 3.3.1:修复属性转换器回归——fromAttribute现在可返回nullundefined(PR #4976);SSR 私有支持中避免指令类的重复 patch(PR #4988)。
  • 3.3.0附带:修复初始 changed properties 值不一致(PR #4949);改为显式导入 barrels,兼容现代 Node 的 ESM 解析(PR #4956)。同步升级@lit/reactive-element@2.1.0lit-element@4.2.0lit-html@3.3.0(见 CHANGELOG 依赖更新节)。

四、指令体系的演进与行为变更

CHANGELOG 中大量条目围绕指令(directive)展开,指令是 Lit 模板中处理动态值逻辑的核心机制。相关源码位于 packages/lit-html/src/directives/。

4.1ref指令:断开即清空(3.1.4 / 3.3.3)

ref指令用于在渲染期间获取元素引用。3.1.4起保证:当元素被断开(disconnected)时,ref()提供的值恒为undefined(PR #4646)。实现见 ref.ts:_updateRefValue!this.isConnected时强制将元素置为undefineddisconnected()生命周期中会清空 ref 盒子(ref.ts),reconnected()时恢复。3.3.3进一步保证内部 ref 为undefined时也能优雅断开。

import {ref, createRef} from 'lit/directives/ref.js'; const inputRef = createRef(); render(html`<input ${ref(inputRef)}>`, container); // 元素断开后 inputRef.value 为 undefined

配套能力:2.7.6允许向ref()undefined(PR #3968),并将RefOrCallback泛型化(PR #3969);2.2.2修复了自动绑定的类方法作为回调时可能错误收到undefined的 Bug(PR #2691)。

4.2choose指令:类型推断收紧(3.0.1)

choose()是一个"无 fallthrough 的 switch 表达式"(choose.ts):按严格相等匹配value与 case,命中第一个即调用对应函数,否则执行可选默认分支:

${choose(this.section, [ ['home', () => html`<h1>Home</h1>`], ['about', () => html`<h1>About</h1>`], ], () => html`<h1>Error</h1>`)}

3.0.1改进了类型推断,正确限制了从 value 推断出的 case 类型(PR #4240)。CHANGELOG 特别提示:如果升级后出现类型错误,说明存在不可达的 case 分支(应删除),或 value 的类型并集缺少某个合法 case。

4.3when指令:条件值作为回调参数(3.0.1)

when()是三元表达式的便捷包装(when.ts)。3.0.1起,when()将提供的条件值作为参数传给 case 函数(PR #4310),从而基于真值性实现类型收窄:

${when(this.user, (u) => html`User: ${u.username}`, () => html`Sign In...`)}

4.4 2.x 时代新增的指令

  • keyed(key, value)(2.1.0,PR #2337):key 变化时清空并重建 part。
  • choose()(2.1.0,PR #2341):见上文。
  • queryAssignedElements装饰器(2.1.0,PR #2327):声明式调用HTMLSlotElement.assignedElements()selector选项支持 CSS 选择器过滤。
  • asyncReplace修复(3.1.1,PR #4409):值未变化时正确重渲染。

4.5 指令相关的 Dev 模式警告

Lit 在开发构建(development build)中提供警告,帮助提前发现错误:

  • 3.1.2:新增 DEV_MODE 错误,捕获重复的属性绑定,避免静默错误(PR #4523)。
  • 3.0.2:若在非静态html标签函数中检测到literal/unsafeStatic等静态值,发出警告——这些值只能用于从lit/static-html.js导入的静态html(PR #4345)。
  • 3.1.1:在 dev 模式警告直接将this.requestUpdate作为事件监听器绑定的写法(PR #4473)。
  • 3.3.0:dev 模式警告改为在包导入后的下一个微任务发出,为使用者提供更充分的抑制时机(PR #4901)。

五、SSR 能力的渐进增强

CHANGELOG 中 SSR 相关条目集中在 2.x 阶段,为 3.x 的稳定运行奠定了基础:

  • 2.3.0(PR #3156):Lit 及其底层库可以在 Node 中直接导入而不崩溃,无需再加载@lit-labs/ssr的 dom-shim。
  • 2.6.0(PR #3522):Node 环境下 Lit 自动引入最小 DOM shims(来自新包@lit-labs/ssr-dom-shim,导出HTMLElementCustomElementRegistry与默认customElements单例),覆盖大多数 SSR 场景。仓库对应实现位于 packages/labs/ssr-dom-shim/src/。
  • 2.7.0:SSR 渲染带内部(internals)的 Lit 元素时会反射 ARIA 属性,并在水合时移除(PR #3677);改进带绑定节点的 SSR 渲染,避免在<textarea>等"原始文本元素"内插入注释(PR #3667,需@lit-labs/ssrlit-html同步升级)。
  • isServer导出(2.4.0,PR #3318):lit包导出isServer变量,在 Node 中为true、浏览器中为false(实现见 is-server.ts)。可用于按环境编写组件逻辑;注意其生效前提是工具链支持"node"export condition。
  • 2.4.0同时为lit包补充"types"export condition,使 TypeScript 的moduleResolution: "nodenext"可用(PR #3320)。

六、开发体验与包工程化改进

6.1 双构建产物:prod 与 development

2.5.0起(PR #3507),lit-htmlreactive-element提供未压缩、带 dev 警告的 development 构建,用于浏览器开发调试。这在 packages/lit/package.json 的exports映射中清晰可见:每个导出入口的types均指向./development/index.d.ts,构建脚本build:ts通过 tsc 产出development/目录,build:ts:types用 treemirror 将.d.ts镜像到包根(见 package.json wireit 配置)。

6.2 导出映射与模块解析的持续修正

  • 2.0.0-rc.4:将package.jsonexports字段从已废弃的"子路径文件夹映射"语法(/后缀)改为显式逐文件列表,要求用户按扩展名导入(PR #2103)。
  • 2.2.8:为各模块补充"types"导出条目(PR #3132)。
  • 2.2.3:强制在导入中使用文件扩展名,兼容旧版 TypeScript 编译器(PR #2732)。
  • 3.1.2:为带"node"export condition 的包补充"browser"条件入口,修复 Node 测试运行器模拟浏览器环境时错误加载"node"入口的问题(PR #4485)。
  • 3.2.1:将 Rollup 压缩插件回退为rollup-plugin-terser,因为@rollup/plugin-terser的 Bug 破坏了压缩名称前缀机制(PR #4782)。
  • 2.2.3起 npm 发布不再包含src/目录与测试文件(PR #1964、PR #3871),减小包体积。

6.3 安全加固

  • 2.7.6(PR #3987):CompiledTemplateh字段改为TemplateStringsArray类型,防止通过 JSON 注入伪造CompiledTemplate
  • 2.2.2(PR #2642):为StaticValues增加额外的安全品牌检查;2.2.2(PR #2646)同时警告:绕过模板字符串数组品牌检查的行为可能引入安全漏洞。

七、装饰器与生命周期修复汇总

CHANGELOG 中与装饰器、生命周期相关的修复值得关注:

  • @query缓存 Bug(3.1.0,PR #4282):带cache标志的@query字段在首次更新前访问时,不再永久缓存null,且 DEV_MODE 下会发出警告。
  • @query类型放宽(3.0.1,PR #4284):允许null出现在@query()装饰字段的类型中。
  • 控制器生命周期隔离(3.1.0,PR #4388):在响应式控制器生命周期中新增/移除控制器,不再影响其他控制器的执行。
  • renderRoot保障(3.1.0,PR #4387):确保首次更新前renderRoot已存在。
  • 属性转换器回归修复(3.3.1,PR #4976):fromAttribute可返回nullundefined
  • 自定义转换器this绑定(2.3.0,PR #3120):为自定义属性转换器方法绑定this
  • 子类初始化器隔离(2.4.1,PR #3374):子类新增的初始化器不再被错误添加到父类。
  • requestUpdate()内部参数清理(3.1.1,PR #4413):移除未使用的内部参数。
  • 标准私有访问器变更检测(3.3.2,PR #4999):修复带装饰器的标准私有访问器的变更检测。

八、升级路线与迁移建议

综合 CHANGELOG 的版本脉络,给出以下可操作的升级建议:

  1. 从 2.x 升级到 3.x 前,先确认目标环境不含 IE11;检查是否仍在导入experimental-hydrate模块(应改用@lit-labs/ssr-client);将@queryAssignedNodes('list', true, '.item')迁移为@queryAssignedElements({slot: '', flatten: false, selector: '.item'});若自定义了属性访问器,确认是否需要noAccessor: true并自行调用requestUpdate()
  2. 升级后开启 dev 模式,借助 duplicate attribute binding、静态值误用、异步performUpdaterequestUpdate作事件监听器等新警告快速定位潜在问题。
  3. 新代码优先采用 3.3.x 能力:为需要反射的属性启用useDefault: true;渲染数学公式时使用mathml模板标签;使用when/choose的窄化回调参数获得更好的类型安全。
  4. SSR 场景:确认工具链支持"node"/"types"export condition,以便isServernodenext模块解析正确工作。

参考路径

  • 变更日志原文:packages/lit/CHANGELOG.md
  • 聚合包入口:packages/lit/src/index.ts、packages/lit/package.json
  • 响应式属性与生命周期:packages/reactive-element/src/reactive-element.ts
  • 模板标签(html/svg/mathml):packages/lit-html/src/lit-html.ts
  • 指令实现:packages/lit-html/src/directives/
  • SSR DOM shim:packages/labs/ssr-dom-shim/src/

【免费下载链接】litLit is a simple library for building fast, lightweight web components.项目地址: https://gitcode.com/GitHub_Trending/li/lit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询