装饰器:就是一个方法,可以注入到类,方法,属性参数上来扩展类,方法,参数的功能
装饰器写法:普通装饰器(无法传参)、装饰器工厂(可传参)
类装饰器 在类声明之前被声明(紧靠类声明)。应用于类构造函数,可以用来监视,修改或替换类定义。
普通装饰器
function logClass(params:any){ console.log(params); //params 即为 HttpClient类 params.prototype.apiUrl = 'xxx'; } // 用@+装饰器名称来表示 @logClass class HttpClient { } var h:any = new HttpClient(); console.log(h.apiUrl); //xxx
装饰器工程
function logClass(params:string){ console.log(params); //params 即为装饰器传入的参数 return function(target:any){ //target为 HttpClient类 target.prototype.apiUrl = params; } } // 用@来表示 @logClass('hello') class HttpClient { } var h:any = new HttpClient(); console.log(h.apiUrl); //hello
类装饰器重载构造函数以及方法
function logClass(params:any){ return class extends params{ apiUrl:string = '我是修改后的'; getData(){ this.apiUrl = this.apiUrl + '.....'; console.log(this.apiUrl); } } } // 用@来表示 @logClass class HttpClient { apiUrl:string | undefined constructor(){ this.apiUrl = '我在构造函数里'; } getData(){ console.log(this.apiUrl); } } var h:any = new HttpClient(); h.getData(); //我是修改后的......
属性装饰器 表达式会在运行时当做函数被调用传入2个参数 :1对于静态资源来说是类的构造函数,对于实例成员是类的 原型对象 2成员的名字
function logAttr(params:any){ //param 属性修饰器传入的参数 return function(target:any,attr:any){ //target 类的实例 attr 属性名 console.log(target) console.log(attr) target[attr] = params; } } class HttpClient { @logAttr('属性装饰器。。。') apiUrl:string | undefined constructor(){ } getData(){ console.log(this.apiUrl); } } var h:any = new HttpClient(); h.getData(); //属性装饰器。。。
方法装饰器 应用到方法的属性描述上,可用来监视修改或者替换方法定义
运行时传入下列3个参数
1.对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象
2.成员的名字
3.成员的属性描述符
//扩展属性和方法 function get(params:any){ //param 属性修饰器传入的参数 return function(target:any,methodName:any,describe:any){ //target 类的实例 attr 属性名 console.log(target) console.log(methodName); console.log(describe.value) target.url = 'xxxxx'; target.run = function(){ console.log('run'); } } } class HttpClient { apiUrl:string | undefined constructor(){ } @get("www.baibai.com") getData(){ console.log('getData方法里'); } } var h:any = new HttpClient(); console.log(h.url); h.run();
//修改当前的方法 function get(params:any){ //param 属性修饰器传入的参数 return function(target:any,methodName:any,describe:any){ //target 类的实例 attr 属性名 console.log(target) console.log(methodName); console.log(describe.value) let oMethod = describe.value; describe.value = function(...args:any[]){ args = args.map((value)=>{ return String(value) }) console.log(args); oMethod.apply(this,args); } } } class HttpClient { apiUrl:string | undefined constructor(){ } @get("www.baibai.com") getData(...args:any[]){ console.log('getData方法里'); } } var h:any = new HttpClient(); h.getData(12,'xxx');
方法参数装饰器 (不常用)
参数装饰器表达式会在运行时当做函数被调用,可以使用参数装饰器为类的原型增加一些元素数据,传入下列3个参数
1.对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象
2方法的名字
3.参数在函数参数列表中的索引
function logParams(params:any){ return function(target:any,methodName:any,paramsIndex:any){ target.url = params; } } class HttpClient { apiUrl:string | undefined constructor(){ } getData(@logParams('xxx') uuid:any){ console.log('getData方法里'); } } var h:any = new HttpClient(); console.log(h.url)
四种装饰器执行顺序
属性 --> 方法 --> 方法参数(从后向前执行 2 -> 1 )--> 类装饰器 (从后向前 2 -> 1)