在 Angular 开发中,会使用到很多装饰器,比如在定义 Angular的模块时,需要使用 NgModule 装饰器修饰 AppModule 类;在定义组件时使用 Component 装饰器修饰组件类。但什么是装饰器?它的工作原理是什么样的呢? 本系列带大家深入理解 Angular 中的装饰器
什么是装饰器(Decorator)?
装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上。 如果读者有其它高级语言(比如Java, C#等)的一些经验,就会发现这和其它语言中的注解(annation)很相似。
装饰器使用 @expression这种形式,expression求值后必须为一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入。装饰器本身其实就是一个函数,理论上忽略参数的话,任何函数都可以当做装饰器使用。
一个最简单的装饰器(Decorator)
新建一个 hello.ts 文件,在文件中定义函数 Hello 如下:
1 | function Simple() { |
这样就得到了一个装饰器: Hello, 采用的是闭包的定义方式,参数 who 是装饰器能能接收的参数。下面让我们在类中使用这个装饰器, 简单的定义一个类,给它加上 Hello 装饰器,
1 | () |
编译 typescript, 将生成对应的 hello.js 文件,如果编译时遇到 ts1219 的错误,可以参考 处理 error TS1219 (Experimental support for decorators is a feature that is subject to change in a future release) 错误 然后在 node 中运行
1 | tsc -p ./ |
系统将输出:
1 | This is a simple |
从运行结果可以看到,Simple中返回的函数被执行了。但我们在 hello.ts 中并没有写任何调用函数的代码,也没有写任何使用 SimpleClass 的代码(包括 new 一个类的实例)。那这段代码时怎么执行的呢?
其实魔术就在 javascript 代码编译的时候完成的,我们知道 typescript 需要编译为 javascript 在运行,但其实 javascript 在运行之前也需要编译,装饰器就是一个在 javascript 编译阶段执行的函数。所以我们看到的结果就是并没有写调用函数和使用类的代码,但装饰器还是被执行了。也就是说,通过装饰器这样的语法,我们获得了在编译阶段执行指定操作的能力。
下一步
在 下一篇文章 ,我们将开始向大家展示不同类型的装饰器(Decorator)
附 - 执行案例所必要的设置
在TypeScript中装饰器还属于实验性语法,所以要想使用必须在配置文件中 tsconfig.json 编译选项中开启,在 Angular 项目中,这个开关在项目目录下的 tsconfig.json 文件中,
1 | { |
选项 experimentalDecorators 指明在当前的项目中是否启用装饰器,默认为 true。 如果不是在 Angular 环境,可以参考 处理 error TS1219 (Experimental support for decorators is a feature that is subject to change in a future release) 错误 进行设置