天天看點

ts 裝飾器學習總結

裝飾器文法

  1. 沒參數 @方法名稱
  2. 有參數 @方法名稱(參數)

    ts裝飾器以關鍵字@開頭 必須在class 中

    裝飾器就是一個函數 在ts編譯成js時執行

1.類裝飾器

//定義裝飾器 
const testClass = (params?:any)=>(target:any)=>{
	//設定目标類Test value 為裝飾器傳進來的參數
    target.prototype.value = params
}
// 調用普通裝飾器
@testClass('測試') 
class Test {
    value:any
    
}
let test = new Test()
console.log(test.value)
           

類裝飾器實用案例

不太容易看懂,建議跟着代碼敲一遍。

/**
 * 類裝飾器重載構造函數
 * 類裝飾器表達式會在運作時當作函數被調用,類的構造函數作為其唯一的參數
 * 如果類裝飾器傳回一個值,它會使用提供的構造函數來替換類的聲明
 * @param params 參數
 * @param target HttpClient 原型
 * @returns 用傳回的類重寫構造函數
 */
 
const logClass = (params:any)=> (target:any)=>{ 
  
    return class  extends target{
        params = params
        apiUrl = '修改後的apiUrl'
        testAttribute = '測試添加屬性' 
        getData(){ // 覆寫 getData 方法
            this.apiUrl += '----'
            console.log(this.apiUrl); //修改後的apiUrl----
        }
       
        testMethod(){
            console.log('測試添加方法')
            return '測試添加方法'
        }
    }
} 

 @logClass('參數')
class HttpClient {
    public apiUrl: string | undefined; 
    getData() {
        console.log(this.apiUrl);
    }
    origin(){ //因為裝飾器中沒有 origin 方法是以 他沒有别覆寫掉
     
        return "我沒有覆寫"
    }

}
var http: any = new HttpClient();

console.log(http.apiUrl) //修改後的apiUrl
http.getData(); //執行了裝飾器裡面的方法
console.log(http.testMethod()) //測試添加方法
console.log(http.apiUrl) //修改後的apiUrl----
console.log(http.testAttribute) //測試添加屬性
console.log(http.params) //測試添加參數 
console.log(http.origin()) //測試添加參數 
           

2.方法裝飾器(用的最多)

/**
 * 
 * @param params 參數
 * @param target class 
 *  @param methodsName  裝飾函數名稱
 * @param desc 函數描述  裡面有個value 為目前函數
 */
const testMethods =(params?:any)=>(target:any,methodsName:any ,desc:any )=>{
 let _methods   =  desc.value; //儲存需要封裝的函數
    
 desc.value = function(){ // 覆寫封裝函數并添加 try catch 
     try {
      return  _methods.apply(this) // 借用封裝的函數并傳回結果,記得寫 return
     } catch (error) {
        console.log(`抱歉${methodsName}出錯了`)  
     }
 }

} 


class Test {
    value:any
    //調用 函數裝飾器
    @testMethods() //裝飾test 函數 記得不能寫;
    test(){
        錯誤 //寫一個錯誤測試一下testMethods效果
    } 
}
let test = new Test() 

test.test()//調用test 方法
           

3.屬性裝飾器

/**
 * 屬性裝飾器隻能接收到兩個參數
 * @param target Test 對應的 prototype
 * @param key  屬性名字
 */

const number = (params: any) => (target: any, key: string):PropertyDescriptor | void  => {
    //設定 Test 中的age (裝飾屬性) = Number(params) 
    target[key] = Number(params) 

    // return {
    //     configurable?: boolean; //是否可以設定
    //     enumerable?: boolean; // 是否可以循環
    //     value?: any; // 強制設定他的值,别人就無法覆寫你的值(不建議使用)
    //     writable?: boolean; // 是否可改
    // }
    
}
 

class Test {
    @number('23') // 設定年齡并轉成字元串
    age = 123 // 有值把上面的覆寫

    @number('23') // 設定年齡并轉成字元串
    age2 
}

const test = new Test();
console.log(test.age) //  123
console.log(test.age2) //24
           

4.參數裝飾器(暫時沒找到他有什麼用)

/**
 * 參數裝飾器定義
 * @param params 傳進來的參數
 * @param target  Test的原型  Test.prototype
 * @param methodName // 目前函數名稱
 * @param paramIndex 所在函數參數中的下标 
 */
const userName = (params: any) => (target: any, method: string, paramIndex: number) => {
    target.name = params
}

class Test {
    age: any
    setAge(@userName('老吳') age: any) {
        console.log(age)
        this.age = age
    }

} 

const test = new Test();
test.setAge(23)
console.log(test.name) //老吳
console.log(test.age) // 23