TS: Decorator, one of the biggest achievements
1. Definition
- Decorator: A decorator is a special type of declaration that can be attached to a class declaration, method, attribute or parameter, and can modify the behavior of the class;
- The decorator is essentially a method, which can be injected into classes, methods, and attribute parameters to expand the functions of classes, methods, attributes, and parameters;
- Common decorators are: class decorators, attribute decorators, method decorators, parameter decorators ;
- There are two types of decorators: ordinary decorators (can not pass parameters) and decorator factories (can pass parameters);
2. Class decorator
-
The class decorator is declared before the class declaration. It is used in the class constructor and can be used to monitor, modify, and replace the definition of the class.
-
Normal decorator mode
// 类装饰器 function logClass(params : any){ // params就是当前类 console.log(params); params.prototype.url = '动态扩展的属性'; params.prototype.run = ()=>{ console.log('动态扩展方法'); } } @logClass class HttpClient { constructor() { } } let http : any= new HttpClient(); //打印 HttpClient {} console.log(http.url); //打印 动态扩展的属性 http.run(); // 打印 动态扩展的方法
-
Decorator factory pattern
function logClass(params:string){ return function(target : any){ //target为当前类 console.log(target); console.log(params); // params为参数 target.prototype.url = params; } } @logClass('hello') class HttpClient{ constructor(){ } } let http = new HttpClient(); console.log(http.url); // 打印 hello
-
Constructor of overloaded class
// 重载构造函数 function logClass(target){ console.log(target); return class extends target{ url : string = '我是修改后的url'; getData(){ console.log(this.url + '.'); } setData(api : string){ this.url = api; } } } @logClass class HttpClient{ public url : string | undefined; constructor(){ this.url = "我是构造函数里的url" } getData(){ console.log(this.url); } } let http : any = new HttpClient(); http.getData(); // 打印 我是修改后的数据
3. Attribute Decorator
-
The attribute decorator accepts two parameters:
- For static members, it is the constructor of the class; for instance members, it is the prototype object of the class;
- Member name
// 类装饰器 function logClass(params:string){ return function(target : any){ //target为当前类 console.log(target); console.log(params); // params为参数 target.prototype.url = params; } } // 属性装饰器 function logProperty(params:any){ return function (target : any,attr : any){ console.log(target); // 类的原型对象 console.log(attr); // 属性的名称 target[attr] = params; } } @logClass('hello') class HttpClient{ @logProperty('heihei') public url : any | undefined; constructor(){ }; getData (){ console.log(this.url); } } let http = new HttpClient(); console.log(http.url); // 打印 heihei
4. Method decorator
-
Similarly, method decorators can be used to monitor, modify, and replace method definitions;
-
Three parameters are received:
- For static members, it is the constructor of the class, and for instance members, it is the prototype object;
- Member name
- The attribute descriptor of the member;
// 方法装饰器 function getMethod(params : any){ return function(target:any,methodName : any,desc : any){ console.log(target); console.log(methodName); console.log(desc); target.name = 'xxx'; target.run = ()=>{ console.log('run'); } } } class HttpClient{ public url : string; constructor() { } @getMethod('http://www.baidu.com') getData(){ console.log(this.url); }; }
-
Modify the original method:
// 方法装饰器 function getMethod(params : any){ return function(target:any,methodName : any,desc : any){ console.log(target); console.log(methodName); console.log(desc); target.name = 'xxx'; target.run = ()=>{ console.log('run'); } // 保存当前方法 let omethod = desc.value; desc.value = function (...args : any[]){ args = args.map((value)=>{ return String(value); }) console.log(args); // 在新替换的函数里执行原函数 omethod.apply(this,args); } } } class HttpClient{ public url : string; constructor() { } @getMethod('http://www.baidu.com') getData(...args : any[]){ console.log("我是getData里的方法"); }; } let http = new HttpClient(); http.getData('yivi');
5. Method parameter decorator
-
The method parameter decorator expression will be called as a function at runtime. You can use the parameter decorator to add some element data to the prototype of the class:
- For static members, it is the constructor of the class, and for instance members, it is the prototype object;
- The name of the method;
- The index of the parameter in the parameter list of the function;
// 方法参数装饰器 function logParams(params : any){ return function (target : any,methodName : any,paramsIndex : any){ console.log(params); console.log(target); console.log(methodName); console.log(paramsIndex); target.api = params; } } class HttpClient { public url : string; constructor() { } getData(@logParams('uuid') uuid : any){ console.log(uuid); } } let http = new HttpClient(); http.getData('12345'); console.log(http.api);
6. Execution order of decorators
-
Attribute decorator>>Method decorator>>Method parameter decorator>>Class decorator;
-
Similar decorators are executed from bottom to top;
-
Readers can implement the decorator sequence example by themselves through the above example.