装饰器
定义:装饰器是一个方法,可以注入到类、方法、属性参数上类扩展、属性、方法、参数的功能
1.类装饰器
普通饰器
不能传参数
// 定义一个装饰器
function logClass(param:any){
console.log(param)//输出:ƒ HttpClient() {}
// 扩展类的属性与方法
param.prototype.apiUrl="xxx"
param.prototype.run=function(){
console.log("动态扩展的run方法")
}
}
@logClass
class HttpClient{
constructor(){}
getData(){
}
}
let h:any = new HttpClient()
h.run()//动态扩展的run方法
装饰器工厂
可以传参
// 定义一个装饰器工厂
// param接收自己传的参数
// target接收类信息
function logClass(param:string){
return function(target:any){
console.log(param,target)//xxx ƒ HttpClient() {}
// 属性扩展
target.prototype.url = param
}
}
@logClass("xxx")
class HttpClient{
constructor(){}
getData(){
}
}
let h:any = new HttpClient()
console.log(h.url)//xxx
使用装饰器重载类方法
// 定义一个装饰器类重载方法
function logClass(param:any){
return class extends param{
api:any="修饰器修改的api"
getData(){
console.log("装饰器重载的方法")
}
}
}
@logClass
class HttpClient{
api:string
constructor(){
this.api="构造函数的api"
}
getData(){
}
}
let h:any = new HttpClient()
h.getData()//装饰器重载的方法
console.log(h.api)//修饰器修改的api
2.属性装饰器
接收两个参数
// 属性装饰器
// target接收类的原型对象
// param接收自己传入参数值
// attr接收修饰的属性名称
function logProps(param:any){
return (target:any,attr:any)=>{
console.log(param,target,attr)//xxx {getData: ƒ, constructor: ƒ} api
// 修改属性
target[attr]=param
}
}
// @logClass
class HttpClient{
@logProps("xxx")
api:string|undefined
constructor(){
}
getData(){
console.log(this.api)
}
}
let h:any = new HttpClient()
h.getData()//xxx
3.方法装饰器
// 方法装饰器
// param:传入参数
// target:被修饰的是静态成员,则是类的构造函数
// 被修饰的是实例成员,则是类的原型对象
// methodName:被修饰方法的方法名
// des:成员的属性描述符(des.value是当前方法)
function logMethod(param:any){
return function(target:any,methodName:string,des:any){
console.log(param,target,methodName,des)
// 扩展属性
target.url="xxsss"
// 扩展方法
target.run=function(){
console.log("这是扩展的方法")
}
// 修改装饰器的方法
// 1.保存当前方法
let md = des.value
//将原方法的参数替换为string类型
des.value = function(...args:any[]){
args=args.map((item)=>String(item))
console.log(args)
// 对象冒充,来修改方法,若不写,则将会替换原方法
md.apply(this,args)
}
}
}
class HttpClient{
api:string|undefined
constructor(){
}
@logMethod("xxxx")
getData(){
console.log(this.api)
}
}
let h:any = new HttpClient()
h.run()//这是扩展的方法
console.log(h.url)//xxsss
h.getData(123,665)
4.方法参数装饰器
// 方法参数装饰器
// 在执行方法时,调用方法参数装饰器,给类的原型对象增加属性,也可以修改参数
// param:传入参数
// target:被修饰的是静态成员,则是类的构造函数
// 被修饰的是实例成员,则是类的原型对象
// methodName:被修饰方法的方法名
// paramIndex:参数索引下标
function logParams(param:any){
return function(target:any,methodName:any,paramIndex:any){
console.log(param,target,methodName,paramIndex)
// 给原型对象增加属性
target.id=param
}
}
class HttpClient{
url:string|undefined
get(@logParams("uuid")uuid:any){
console.log("类里面的实例方法"+uuid)
}
}
let h:any = new HttpClient()
h.get(12233)//类里面的实例方法12233
console.log(h.id)//uuid
总结
装饰器可以对类、方法、属性、参数进行修改、扩展、替换等操作
执行顺序:属性装饰器->方法装饰器->方法参数装饰器->类装饰器
同类装饰器执行顺序:由下向上、由里及外、由后往前