TS: Decorator, one of the biggest achievements

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:

    1. For static members, it is the constructor of the class; for instance members, it is the prototype object of the class;
    2. 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:

    1. For static members, it is the constructor of the class, and for instance members, it is the prototype object;
    2. Member name
    3. 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:

    1. For static members, it is the constructor of the class, and for instance members, it is the prototype object;
    2. The name of the method;
    3. 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.

Guess you like

Origin blog.csdn.net/yivisir/article/details/109738785