Decorator

定义

给对象动态增加职责的方式称为装饰者模式。该模式能够在不改变对象自身的基础上,在程序运行期间给对象动态增加指责

装饰函数

想要为函数增加额外功能,最简单粗暴的方式直接改写函数,但这很不友好,违反 封闭-开放原则

1
2
3
4
5
6
7
var a = function() {alert(1)}
// 改成
var a = function () {
alert(1);
alert(2);
}
a()

在不改变函数源代码的方式能给函数增加功能,这正是开放-封闭原则。通过保存原引用的方式改写函数

1
2
3
4
5
6
7
var a = function() {alert(1)}
var _a = a
a = function() {
_a()
alert(2)
}
a()

编写装饰器

class decorator 类装饰器
method decorator 方法装饰器
property decorator 属性装饰器
parameter decorator 参数装饰器

装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上。 装饰器使用 @expression这种形式,expression求值后必须为一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入。

装饰器工厂

如果我们要定制一个修饰器如何应用到一个声明上,我们得写一个装饰器工厂函数。 装饰器工厂就是一个简单的函数,它返回一个表达式,以供装饰器在运行时调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

function thinFace(name: string) {
console.log(name, '开启瘦脸');
return function(target: string) {
console.log("thinFace(): called");
}
}
function increaseEye(name: string) {
console.log(name, '增大眼睛');
return function(target: string, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("increaseEye(): called");
}
}

@thinFace('cpp')
@increaseEye('niaogege')
export default class Girl {}
// 打印参数

cpp 开启瘦脸
niaogege 增大眼睛
increaseEye(): called
thinFace(): called

在TypeScript里,当多个装饰器应用在一个声明上时会进行如下步骤的操作:

  • 由上至下依次对装饰器表达式求值。
  • 求值的结果会被当作函数,由下至上依次调用(装饰器函数)。

类装饰器 class decorator 类装饰器

类装饰器在类声明之前被声明(紧靠着类声明)。
类装饰器应用于类构造函数,可以用来监视,修改或替换类定义。类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数。即在执行装饰器函数时,会把类构造函数传递给装饰器函数。
如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

function thinFace(constructor: Function) {
onsole.log('thinFace Before', constructor); // 把Girl类构造函数传递给装饰器函数
constructor.prototype.thinFaceF = function (params: any) { // 给构造函数原型上增加新的方法
console.log('become thinFace');
}
}
function classDecorator(value: string) {
console.log('类的装饰器 Before', value);
return function(constructor: Function) {
console.log('接受一个构造函数', value); // 如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。
}
}

@thinFace
@classDecorator('cpp')
export default class Girl {
private greeting: string
constructor(msg: string) {
this.greeting = msg
}
greetName() {
return `Hello!, ${this.greeting}`
}
thinFaceF() {
console.log('Grid 类里的函数');
}
}
// 调用
const g = new Girl('wmh')
console.log('Girl类的实例', g);
g.thinFaceF();
// 类的装饰器 Before
// 接受一个构造函数 cpp
// thinFace Before class Girl
// become thinFace

ts项目的运用

Ts项目中的’vue-property-decorator’拆解

总结

ts报错信息

  • Unable to resolve signature of class decorator when called as an expression.
    This expression is not callable.
    Type ‘void’ has no call signatures.

  • signature 签名

参考链接