裝飾器文法
- 沒參數 @方法名稱
-
有參數 @方法名稱(參數)
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