什么是装饰器?
装饰器是一种编程概念,用于在不修改原始代码的情况下,为代码元素(如函数、方法、类等)添加额外的功能或行为。 装饰器以@符号为前缀,后跟一个函数或类,它附着在类、方法、属性等代码元素上,并在运行时对这些元素进行注释或修改。装饰器的使用主要在两种情况下:
- 在TypeScript中,装饰器是一种特殊类型的声明,用于增强代码功能的声明。它们提供了一种在类、方法、属性等代码元素上注释或修改的方式,使得我们可以通过装饰器来扩展、修改或监视代码的行为。
- 在Python中,装饰器是一个函数或类,用于增强其他函数或方法的功能而不改变其结构。装饰器的本质是一个闭包函数,它接受一个函数作为参数,返回一个新的函数,并在返回的函数中执行原函数以及额外的功能。
装饰器的应用场景广泛,包括但不限于性能测试、打印日志、用户验证、日志记录、性能分析、缓存、权限验证等。通过使用装饰器,可以提高代码的可维护性、灵活性和复用性。
装饰器的种类
//1.类装饰器 ClassDecorator target 构造函数
//2.属性装饰器 PropertyDecorator
//3.参数装饰器 ParameterDecorator
//4.方法装饰器 MethodDecorator PropertyDescriptor
//5.装饰器工厂
//6.import 'reflect-metadata
//7.axios
类装饰器
最初实现
const Base:ClassDecorator = (target) => {
console.log(
target
)
}
@Base
class Http {
}
这是一个简单的函数,我们执行 ts-node index.ts 那么就可以读取到结果
有了构造函数可以干什么?(不去破坏原有的结构)
我不想读原有的几千行代码,我又要增加属性、方法,怎么做?
const Base:ClassDecorator = (target) => {
console.log(target)
target.prototype.name = '胡子铭'
target.prototype.funny = () =>{
console.log('我是XXXX')
}
}
@Base
class Http {
// 。。。。。
}
const http =new Http() as any
http.funny()
console.log(http.name)
Base(Http)
我想要自定义怎么做?使用函数柯里化
函数柯里化==装饰器工厂(定义一个函数,相当于闭包)
const Base = (name:string) => {
const fn:ClassDecorator = (target) =>{
console.log(target)
target.prototype.name = name
target.prototype.funny = () =>{
console.log('11514')
}
}
return fn
}
@Base('qian duan')
class Http {
// 。。。。。
}
const http =new Http() as any
http.funny()
console.log(http.name)
方法装饰器
类里面实现get和post请求
在类的中心呼唤mock(地址:api.apiopen.top/api/getHaoK…)
MethodDecorator可以读出三个属性,target、key、descriptor(这里读取的是原型对象了,不是这个构造函数)
const Base = (name:string) => {
const fn:ClassDecorator = (target) =>{
// console.log(target)
target.prototype.name = name
target.prototype.funny = () =>{
// console.log('11514')
}
}
return fn
}
const Get = (url:string) =>{
const fn:MethodDecorator = (target,key,descriptor) =>{
console.log(target,key,descriptor)
}
return fn
}
@Base('qian duan')
class Http {
@Get('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10')
getList(data:any){
console.log(data)
}
}
const http =new Http() as any
http.funny()
// console.log(http.name)
可以看到我们这三个对象返回的参数
使用axios调用接口
node只能用http,用axios更方便一点
cnpm i axios
import axios from "axios"
const Base = (name:string) => {
const fn:ClassDecorator = (target) =>{
// console.log(target)
target.prototype.name = name
target.prototype.funny = () =>{
// console.log('11514')
}
}
return fn
}
const Get = (url:string) =>{
const fn:MethodDecorator = (target,key,descriptor:PropertyDescriptor) =>{
// console.log(target,key,descriptor)
axios.get(url).then(res =>{
descriptor.value(res.data)
})
}
return fn
}
@Base('qian duan')
class Http {
@Get('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10')
getList(data:any){
console.log(data)
}
}
const http =new Http() as any
http.funny()
// console.log(http.name)
可以照着这个方法实现一个POST请求
//1.类装饰器 ClassDecorator target 构造函数
//2.属性装饰器 PropertyDecorator
//3.参数装饰器 ParameterDecorator
//4.方法装饰器 MethodDecorator PropertyDescriptor
//5.装饰器工厂
//6.import 'reflect-metadata
//7.axios
import axios from "axios"
const Base = (name:string) => {
const fn:ClassDecorator = (target) =>{
// console.log(target)
target.prototype.name = name
target.prototype.funny = () =>{
// console.log('11514')
}
}
return fn
}
const Get = (url:string) =>{
const fn:MethodDecorator = (target,key,descriptor:PropertyDescriptor) =>{
// console.log(target,key,descriptor)
axios.get(url).then(res =>{
descriptor.value(res.data)
})
}
return fn
}
const POST = (url:string) =>{
const fn:MethodDecorator = (target,key,descriptor:PropertyDescriptor) =>{
// console.log(target,key,descriptor)
axios.post(url).then(res =>{
descriptor.value(res.data)
})
}
return fn
}
@Base('qian duan')
class Http {
// @Get('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10')
@POST('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10')
getList(data:any){
console.log(data)
}
}
const http =new Http() as any
http.funny()
// console.log(http.name)
参数装饰器和reflector
import 'reflect-metadata'
import axios from "axios"
const Base = (name:string) => {
const fn:ClassDecorator = (target) =>{
// console.log(target)
target.prototype.name = name
target.prototype.funny = () =>{
// console.log('11514')
}
}
return fn
}
const Get = (url:string) =>{
const fn:MethodDecorator = (target,_:any,descriptor:PropertyDescriptor) =>{
// 取值
const key = Reflect.getMetadata('key',target)
// console.log(target,key,descriptor)
axios.get(url).then(res =>{
descriptor.value(key?res.data[key]:res.data)
})
}
return fn
}
// const POST = (url:string) =>{
// const fn:MethodDecorator = (target,key,descriptor:PropertyDescriptor) =>{
// // console.log(target,key,descriptor)
// axios.post(url).then(res =>{
// descriptor.value(res.data)
// })
// }
// return fn
// }
const Result = () =>{
const fn:ParameterDecorator = (target,propertyKey,parameterIndex) =>{
// console.log(target,propertyKey,parameterIndex)
// 存值
Reflect.defineMetadata('key','result',target)
}
return fn
}
@Base('qian duan')
class Http {
// @Get('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10')
@Get('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10')
getList(@Result() data:any){
console.log(data)
}
}
const http =new Http() as any
http.funny()
// console.log(http.name)
属性装饰器
import 'reflect-metadata'
import axios from "axios"
const Base = (name:string) => {
const fn:ClassDecorator = (target) =>{
// console.log(target)
target.prototype.name = name
target.prototype.funny = () =>{
// console.log('11514')
}
}
return fn
}
const Get = (url:string) =>{
const fn:MethodDecorator = (target,_:any,descriptor:PropertyDescriptor) =>{
// 取值
const key = Reflect.getMetadata('key',target)
// console.log(target,key,descriptor)
axios.get(url).then(res =>{
descriptor.value(key?res.data[key]:res.data)
})
}
return fn
}
// const POST = (url:string) =>{
// const fn:MethodDecorator = (target,key,descriptor:PropertyDescriptor) =>{
// // console.log(target,key,descriptor)
// axios.post(url).then(res =>{
// descriptor.value(res.data)
// })
// }
// return fn
// }
const Result = () =>{
const fn:ParameterDecorator = (target,propertyKey,parameterIndex) =>{
// console.log(target,propertyKey,parameterIndex)
// 存值
Reflect.defineMetadata('key','result',target)
}
return fn
}
const Name:PropertyDecorator =(target,key)=>{
console.log(target,key)
}
@Base('qian duan')
class Http {
// @Get('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10')
@Name
huziming:string
constructor(){
this.huziming = '?'
}
@Get('https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10')
getList(@Result() data:any){
// console.log(data)
}
}
const http =new Http() as any
http.funny()
// console.log(http.name)