装饰器
装饰器是函数,可用于声明式地注释和修改类的行为。
Lit 提供了一组可选装饰器,这些装饰器支持声明式 API,用于注册元素、定义响应式属性和查询属性,或向事件处理程序方法添加事件选项。
例如,@customElement
和 @property()
装饰器允许您以紧凑、声明式的方式注册自定义元素并定义响应式属性
Lit 支持 JavaScript 装饰器提案的两个不同版本 - TypeScript 支持的早期版本,我们称之为实验性装饰器,以及一个新的最终版本,我们称之为标准装饰器。
这两个提案在使用上有一些细微的差别(标准装饰器通常需要accessor
关键字)。我们的代码示例是针对实验性装饰器编写的,因为我们目前建议在生产中使用它们。
有关更多详细信息,请参阅装饰器版本。
内置装饰器
指向“内置装饰器”的永久链接装饰器 | 摘要 | 更多信息 |
---|---|---|
@customElement | 定义自定义元素。 | 定义 |
@eventOptions | 添加事件监听器选项。 | 事件 |
@property | 定义公共属性。 | 属性 |
@state | 定义私有状态属性 | 属性 |
@query | 定义一个返回组件模板中元素的属性。 | Shadow DOM |
@queryAll | 定义一个返回组件模板中元素列表的属性。 | Shadow DOM |
@queryAsync | 定义一个返回 Promise 的属性,该 Promise 解析为组件模板中的元素。 | Shadow DOM |
@queryAssignedElements | 定义一个返回分配给特定插槽的子元素的属性。 | Shadow DOM |
@queryAssignedNodes | 定义一个返回分配给特定插槽的子节点的属性。 | Shadow DOM |
导入装饰器
指向“导入装饰器”的永久链接您可以通过lit/decorators.js
模块导入所有 Lit 装饰器
为了减少运行组件所需的代码量,可以将装饰器单独导入组件代码中。所有装饰器都可以在lit/decorators/<decorator-name>.js
中找到。例如,
启用装饰器
指向“启用装饰器”的永久链接要使用装饰器,您需要使用编译器(如TypeScript或Babel)构建您的代码。
将来,当浏览器原生支持装饰器时,这将不再需要。
在 TypeScript 中使用装饰器
指向“在 TypeScript 中使用装饰器”的永久链接TypeScript 支持实验性装饰器和标准装饰器。我们建议 TypeScript 开发人员现在使用实验性装饰器,以获得最佳编译器输出。如果您的项目需要使用标准装饰器或设置"useDefineForClassFields": true
,请跳到迁移到标准装饰器。
要使用实验性装饰器,您必须启用experimentalDecorators
编译器选项。
您还应该确保useDefineForClassFields
设置值为false
。这仅在target
设置为ES2022
或更高版本时才需要,但建议将其显式设置为false
。这是为了避免在声明属性时出现与类字段相关的问题。
启用emitDecoratorMetadata
不是必需的,也不建议这样做。
将 TypeScript 实验性装饰器迁移到标准装饰器
指向“将 TypeScript 实验性装饰器迁移到标准装饰器”的永久链接Lit 装饰器旨在支持标准装饰器语法(在类字段装饰器上使用accessor
)以及 TypeScript 的实验性装饰器模式。
这允许从添加accessor
关键字到装饰属性开始,逐步迁移出实验性装饰器,而不会改变行为。一旦所有装饰的类字段都使用accessor
关键字,您就可以更改编译器选项以完成迁移到标准装饰器
注意:accessor
关键字是在 TypeScript 4.9 中引入的,带有元数据的标准装饰器需要 TypeScript ≥5.2。
在 Babel 中使用装饰器
指向“在 Babel 中使用装饰器”的永久链接Babel从 7.23 版本开始使用@babel/plugin-proposal-decorators
插件支持标准装饰器。Babel 不支持 TypeScript 实验性装饰器,因此您必须使用 Lit 装饰器和标准装饰器语法,在装饰的类字段上使用accessor
关键字。
通过添加@babel/plugin-proposal-decorators
以及这些 Babel 配置设置,来启用装饰器
注意:Lit 装饰器仅与"version": "2023-05"
一起使用。其他版本,包括以前支持的"2018-09"
,都不支持。
装饰器版本
指向“装饰器版本”的永久链接装饰器是第 3 阶段提案,用于添加到 ECMAScript 标准。编译器(如Babel和TypeScript)支持装饰器,但浏览器尚未实现它们。Lit 装饰器与 Babel 和 TypeScript 兼容,并且在浏览器原生实现它们后也将兼容。
第 3 阶段意味着什么?
这意味着规范文本已经完成,并且已准备好供浏览器实现。一旦规范在多个浏览器中实现,它就可以进入最终阶段,即第 4 阶段,并被添加到 ECMAScript 标准中。第 3 阶段提案只会因为在实现过程中发现了严重问题而改变。
早期装饰器提案
指向“早期装饰器提案”的永久链接在 TC39 提案达到第 3 阶段之前,编译器实现了装饰器规范的早期版本。
其中最重要的是TypeScript 的实验性装饰器,Lit 从一开始就支持它,也是我们目前建议使用的。
Babel 随着时间的推移也支持规范的不同版本,从装饰器插件的"version"
选项可以看出。过去,Lit 2 支持 Babel 用户的"2018-09"
版本,但现在已被放弃,转而支持下面描述的标准"2023-05"
版本。
标准装饰器
指向“标准装饰器”的永久链接标准装饰器是装饰器的版本,它已在定义 ECMAScript/JavaScript 的 TC39 组织中达成第 3 阶段共识。
标准装饰器在 TypeScript 和 Babel 中受支持,浏览器将在不久的将来提供原生支持。
标准装饰器与实验性装饰器之间最大的区别在于,出于性能原因,标准装饰器不能更改被装饰和替换的类成员的类型 - 字段、访问器和方法 - 并且只会生成相同的类型成员。
由于许多 Lit 装饰器生成访问器,这意味着装饰器需要应用于访问器,而不是类字段。
为了方便起见,标准装饰器规范添加了accessor
关键字来声明“自动访问器”。
自动访问器会创建一个 getter 和 setter 对,它们从私有字段读取和写入。装饰器可以包装这些 getter 和 setter。
Lit 装饰器(使用实验性装饰器在类字段上工作 - 例如@property()
、@state()
、@query()
等)必须使用标准装饰器应用于访问器或自动访问器
编译器输出注意事项
指向“编译器输出注意事项”的永久链接标准装饰器的编译器输出不幸的是非常庞大,因为需要生成访问器、私有存储以及装饰器 API 的其他对象。
因此,我们建议希望使用装饰器的用户,如果可能的话,现在使用 TypeScript 实验性装饰器。
将来,Lit 团队计划将装饰器转换添加到我们的可选 Lit 编译器中,以便将标准装饰器编译成更紧凑的编译器输出。浏览器原生支持也将完全消除对任何编译器转换的需求。