装饰器是一种特殊类型的声明,他能附加到类声明方法属性或参数上可以修改类的行为;
说人话就是装饰器是一个方法,作用于类方法属性参数以便修改扩展相应功能。
es7中装饰器Decorators已经有提案了,但是尚未形成标准,在ts中已经进行了支持,但是ts装饰器也是一项实验性特性,在未来的版本中可能会发生改变。若要启用实验性的装饰器特性,你必须在命令行或tsconfig.json里启用experimentalDecorators编译器选项:
tsc --target ES5 --experimentalDecorators
tsconfig.json:
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true
}
}
在不修改类的前提下,用来扩展类的属性或方法
function Decorators(res:any){ //这里随便起,只是个名字
console.log(res);//Animal(){}
//可以看出res就是当前的类
res.prototype.leg = '4';
res.prototype.eat = function(){
console.log('meat')
}
}
@Decorators
class Animal{
constructor(){}
say():void{console.log('alala')}
}
let A = new Animal();
A.leg //4 leg就是未修改类扩展的属性
A.eat() //meat 扩展的方法
以上的例子就是一个普通装饰器(不可传参)
相对于上边没有传参的普通装饰器,实际开发时用的更多的可能还是需要传入参数的;
function Decorators(res:any){
return function(tag:any){
console.log(res) //dahuang
console.log(tag) //Animal(){}
tag.prototype.name= res;
}
}
@Decorators('dahuang')
class Animal{
constructor(){}
}
let A = new Animal();
A.name;//dahuang
function Decorators(res:any){
return class extends res{
leg:number = 4;
say():void{
console.log(this.leg)
}
}
}
@Decorators
class Animal{
leg:number;
constructor(leg){this.leg = leg}
say():void{console.log('alala')}
}
let A = new Animal(3);
A.say()//4
属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数:
//类装饰器
function Decorators(res: any) {
return function (tag: any) { }
}
//属性装饰器
function changeLeg(res: any) {
return function (tag: any, att: any) {
console.log(tag)//Animal(){}
console.log(att)//leg
tag[att] = '8'
}
}
@Decorators('asd')
class Animal {
@changeLeg('3')
leg: number;
constructor() {}
say(){console.log(this.leg)}
}
let A = new Animal();
A.say();//8
应用到方法的 属性描述符上,可以用来监视,修改或者替换方法定义。
方法装饰器需要传入下列3个参数:
function change(res:any){
return function(tag:any,method:any,desc:any){
console.log(tag) //Cat(){}
console.log(method) //say
console.log(desc) //编译版本小于ES5,为undefined。
//尝试时如果init了tsconfig不生效,可能是因为指定了文件名称,从而编译器对其进行了忽略
tag.eat = function(){console.log('meat')}//新增方法
let oMethod = desc.value; //修改方法
desc.value = function(e:string){
console.log(e)
oMethod.call(this,e)
}
}
}
class Cat{
@change('cat')
say(){
console.log('woofwoof')
}
}
@change('window')function fun(){}//error此处装饰器无效
let dahuang = new Cat();
dahuang.eat()//meat
dahuang.say('hello world')//hello world woofwoof
参数装饰器表达式会在运行时当作函数被调用,可是使用其为类的原型增加一些元素数据,传入下列3个参数:
function dec(res:any){
return function(tag:any,_name:any,ind:any){
console.log(tag) //Cat(){}
console.log(_name) //say
console.log(ind) //0
}
}
class Cat{
name:string;
constructor(){}
say(@dec('xxx' sth:string)){console.log(sth)}
}
let cat = new Cat();
cat.say('hello world') //hello world