聊聊Angular中的元数据(Metadata)和装饰器(Decorator)

javascriptjavascript 2023-08-29 12:43:09 737
摘要: 本篇文章继续Angular的学习,带大家了解一下Angular中的元数据和装饰器,简单了解一下他们的用法,希望对大家有所帮助!作为“为大型前端项目”而设计的前端框架,Angular其实有许多值得参考和学习的设计,本系列主要用于研究这...

本篇文章继续Angular的学习,带大家了解一下Angular中的元数据和装饰器,简单了解一下他们的用法,希望对大家有所帮助!

作为“为大型前端项目”而设计的前端框架,Angular 其实有许多值得参考和学习的设计,本系列主要用于研究这些设计和功能的实现原理。本文主要围绕 Angular 中随处可见的元数据,来进行介绍。【相关教程推荐:《angular教程》】

装饰器是使用 Angular 进行开发时的核心概念。在 Angular 中,装饰器用于为类或属性附加元数据,来让自己知道那些类或属性的含义,以及该如何处理它们。

装饰器与元数据

不管是装饰器还是元数据,都不是由 Angular 提出的概念。因此,我们先来简单了解一下。

元数据(Metadata)

在通用的概念中,元数据是描述用户数据的数据。它总结了有关数据的基本信息,可以使查找和使用特定数据实例更加容易。例如,作者,创建日期,修改日期和文件大小是非常基本的文档元数据的示例。

在用于类的场景下,元数据用于装饰类,来描述类的定义和行为,以便可以配置类的预期行为。

装饰器(Decorator)

装饰器是 JavaScript 的一种语言特性,是一项位于阶段 2(stage 2)的试验特性。

装饰器是定义期间在类,类元素或其他 JavaScript 语法形式上调用的函数。

装饰器具有三个主要功能:

  • 可以用具有相同语义的匹配值替换正在修饰的值。(例如,装饰器可以将方法替换为另一种方法,将一个字段替换为另一个字段,将一个类替换为另一个类,等等)。

  • 可以将元数据与正在修饰的值相关联;可以从外部读取此元数据,并将其用于元编程和自我检查。

  • 可以通过元数据提供对正在修饰的值的访问。对于公共值,他们可以通过值名称来实现;对于私有值,它们接收访问器函数,然后可以选择共享它们。

本质上,装饰器可用于对值进行元编程和向其添加功能,而无需从根本上改变其外部行为。

更多的内容,可以参考 tc39/proposal-decorators 提案。

Angular 中的装饰器和元数据

我们在开发 Angular 应用时,不管是组件、指令,还是服务、模块等,都需要通过装饰器来进行定义和开发。装饰器会出现在类定义的紧前方,用来声明该类具有指定的类型,并且提供适合该类型的元数据。

比如,我们可以用下列装饰器来声明 Angular 的类:@Component()@Directive()@Pipe()@Injectable()@NgModule()

使用装饰器和元数据来改变类的行为

@Component()为例,该装饰器的作用包括:

  • 将类标记为 Angular 组件。

  • 提供可配置的元数据,用来确定应在运行时如何处理、实例化和使用该组件。

关于@Component()该如何使用可以参考,这里不多介绍。我们来看看这个装饰器的定义:

// 提供 Angular 组件的配置元数据接口定义
// Angular 中,组件是指令的子集,始终与模板相关联
export interface Component extends Directive {
  // changeDetection 用于此组件的变更检测策略
  // 实例化组件时,Angular 将创建一个更改检测器,该更改检测器负责传播组件的绑定。
  changeDetection?: ChangeDetectionStrategy;
  // 定义对其视图 DOM 子对象可见的可注入对象的集合
  viewProviders?: Provider[];
  // 包含组件的模块的模块ID,该组件必须能够解析模板和样式的相对 URL
  moduleId?: string;
  ...
  // 模板和 CSS 样式的封装策略
  encapsulation?: ViewEncapsulation;
  // 覆盖默认的插值起始和终止定界符(`{{`和`}}`)
  interpolation?: [string, string];
}

// 组件装饰器和元数据
export const Component: ComponentDecorator = makeDecorator(
    'Component',
    // 使用默认的 CheckAlways 策略,在该策略中,更改检测是自动进行的,直到明确停用为止。
    (c: Component = {}) => ({changeDetection: ChangeDetectionStrategy.Default, ...c}),
    Directive, undefined,
    (type: Type<any>, meta: Component) => SWITCH_COMPILE_COMPONENT(type, meta));