在使用Angular中常常遇到装饰器,如下:
@NgModule({
declarations: [
AppComponent,
HighlightDireactive
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
---------------------------------------
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
首先,什么是装饰器?
装饰器是一种函数,用于增强class的功能。写成@ + 函数名形式,如@NgModule,可以用来装饰四种类型的值。
- 类
- 类的属性
- 类的方法
- 属性存取器(accessor)
在TS中这么定义装饰器
type Decorator = (
value: Input,
context: {
kind: string;
name: string | symbol;
access: {
get?(): unknown;
set?(value: unknown): void;
};
private?: boolean;
static?: boolean;
addInitializer?(initializer: () => void): void;
}) => Output | void;
包括两个参数,value和context。
value:所要装饰的值,某些情况下可能是undefined(装饰属性时)。context:上下文信息对象。
@testable
class MyTestableClass {
// ...
}
function testable(target) {
target.isTestable = true;
}
MyTestableClass.isTestable // true
testable装饰器作用于类MyTestableClass,给类加了静态属性isTestable。
装饰器的行为可以表示为如下形式,A = decorator(A) || A;decorator(A)为类A进行装饰。
@decorator
class A {}
// 等同于
class A {}
A = decorator(A) || A;
装饰器在对类进行装饰的过程中,可以进行传参,因为装饰器就是一个函数
function testable(isTestable) {
return function(target) {
target.isTestable = isTestable;
}
}
@testable(true)
class MyTestableClass {}
MyTestableClass.isTestable // true
@testable(false)
class MyClass {}
MyClass.isTestable // false
由此可以类比Angular中的装饰器。
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'my-app';
}
其中,@Component中的对象是对AppComponent类进行装饰的辅助工具。
装饰器不仅可以装饰类,还可以装饰类的属性。
在Angular如下体现
export class AppComponent {
@Input() inputValue:string;
@ViewChild("childDom") childDom:ElementRef;
title = 'my-app';
}
在类声明时,我们想为类的实例做装饰,此时类的实例还没有生成。依照JS的特性,此时我们可以在类的prototype对象上绑定属性和方法,再通过原型链实现实例拥有该类的某些“装饰属性”。如下readOnly装饰器
function readonly(target, name, descriptor){
descriptor.writable = false;
return descriptor;
}
readonly(Person.prototype, 'name', descriptor);
// 类似于
Object.defineProperty(Person.prototype, 'name', descriptor);
详情看阮一峰博客