装饰器语法
- 没参数 @方法名称
-
有参数 @方法名称(参数)
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