本书未发布
装饰器
类装饰器
function addNameAndEat(target: Function) {
// target 就是要装饰的类
target.prototype.name = 'xiaoming'
target.prototype.eat = function(){}
}
@addNameAndEat
class Person {
name: string
eat: Function
constructor(){}
}
let p:Person = new Person()
console.log(p.name)
p.eat()
类装饰器工厂
- 装饰器可以传递参数
function addNameAndEatFactory(name: string) {
return function addNameAndEad(target: Function) {
// target 就是要装饰的类
target.prototype.name = name
target.prototype.eat = function(){}
}
}
@addNameAndEatFactory('xiaoming')
class Person {
name: string
eat: Function
constructor(){}
}
let p:Person = new Person()
console.log(p.name)
p.eat()
属性装饰器
可以装饰属性, 也可以装饰方法
namespace a { //如果装饰的是实例属性的话, 那么 target 是构造函数的原型 function upperCase(target: any, propertyKey: string) { let value = target[propertyKey] const getter = () => value const setter = (newVal: string) => {value = newVal.toUpperCase()} if (delete target[propertyKey]) { Object.defineProperty(target, propertyKey, { get: getter, set: setter, enumerable: true, configurable: true }) } } // 如果装饰的是静态属性的话, 那么 target 是构造函数本身 function staticPropertyDecorator(target: any, propertyKey: string) { console.log(target, propertyKey) } function noEnumerable(target: any, propertyKey: string, descriptor: PropertyDecorator) { // 变成不可枚举 descriptor.enumerable = false } // 方法装饰器 function toNumber(target: any, propertyKey: string, descriptor: PropertyDecorator) { let oldMethod = descriptor.value descriptor.value = function(...args: any[]) { args = args.map(item => parseFolat(item)) return oldMethod.apply(this, args) } } class Person { // 装饰 name @upperCase name:string = 'xiaoming' @staticPropertyDecorator public static age: number = 18 constructor() {} @noEnumerable getName() { console.log(this.name) } @toNumber sum(...args: any[]) { return args.reduce((accu: number, item: number) => accu+ item,0) } } }
参数装饰器
namespace b {
// 如果修饰的是静态成员, 那么 target 就是构造函数, 如果是非静态成员, target 就是构造函数原型
// methodName 是方法名称
// paramIndex 是参数的索引
function addAge(target: any, methodName, paramIndex: number) {
target.age = 10
}
class Person {
age: number
login(username: string, @addAge password: string) {
console.log(this.age, username, password)
}
}
}
装饰器的执行顺序
- 一般是从内往外执行, 先内后外
- 类装饰器是最后执行的, 如果一个类有多个装饰器, 那么后写的装饰器先执行
- 方法和方法参数中的装饰器, 会先执行参数的装饰器, 然后再执行方法的
- 方法和属性的装饰器, 谁在前面, 就先执行谁