装饰器是一种特殊类型的声明,它能够被附加到类声明、方法、属性或参数上,可以修改类的行为。 通俗来讲,装饰器就是一个方法,可以注入到类、方法、属性、参数上来扩展类、方法、属性、参数的功能。 常见的装饰器有:类装饰器、方法装饰器、属性装饰器、参数装饰器。
装饰器的写法: 普通装饰器(无法传参) 、装饰器工厂(可传参)
// 普通装饰器 类装饰器: 用来监视、修改、替换类定义
function logClass(params: any) { // params就是当前类
console.log(params)
params.prototype.apiUrl = '动态扩展的属性'
params.prototype.run = function () {
console.log('我是一个run方法')
}
}
@logClass
class HttpClient{
constructor() {
}
getData() {
}
}
var http:any = new HttpClient()
console.log(http.apiUrl)
http.run()
// 装饰器工厂(可传参) 类装饰器
function logClass(params: string) {
return function (target:any) {
console.log(target) // 当前类
console.log(params) // www.baidu.com
target.prototype.apiUrl = params
}
}
@logClass('www.baidu.com')
class HttpClient{
constructor() {
}
getData() {
}
}
var http:any = new HttpClient()
console.log(http.apiUrl)
/**
* 例子: 重载构造函数
* 类装饰器: 会在运行时当做函数被调用,类的构造函数作为其唯一的参数
* 如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明
*/
function logClass(target:any) {
console.log(target) // 当前类
return class extends target {
apiUrl:string = '我是修改后的数据'
getData() {
console.log(this.apiUrl + '000000')
}
}
}
@logClass
class HttpClient{
apiUrl: string
constructor() {
this.apiUrl = '我是构造函数里面的apiUrl'
}
getData() {
console.log(this.apiUrl)
}
}
var http:any = new HttpClient()
http.getData()
/**
* 属性装饰器
*/
function logClass(params:any) {
return function(target:any) {
console.log('类装饰器' + params)
console.log('类装饰器' + target)
}
}
function logProperty(params:any) {
return function(target:any, attr: any) {
console.log('属性装饰器' + params)
console.log(target) // 对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象
console.log('属性装饰器' + attr) // 属性的名字
target[attr]= params
}
}
@logClass('xxx')
class HttpClient{
@logProperty('www.google.com')
public apiUrl: string | undefined
constructor() {
}
getData() {
console.log(this.apiUrl)
}
}
var http:any = new HttpClient()
console.log(http)
http.getData()
/**
* 方法装饰器 用来监视、修改、替换方法的定义
*/
function logMethod(params:any) {
return function (target:any, methodName: string, desc: any) {
console.log(target) // 对于静态成员是类的构造函数,对于实例成员是类的原型对象
console.log(methodName) // 方法名字
console.log(desc) // 对方法的描述
target.name = 'xxx'
target.run = function () {
console.log('run')
}
// 替换getData方法,把修饰器方法里面传入的参数改为string类型
// desc.value = function(...args:any[]) {
// args = args.map(v => String(v))
// console.log(args)
// }
// 修改方法
var oMethod = desc.value
desc.value = function(...args:any[]) {
args = args.map(v => String(v))
console.log(args)
oMethod.apply(this, args)
}
}
}
class HttpClient{
public apiUrl: string | undefined
constructor() {
}
@logMethod('xxxxx') // 把传入的参数变成string类型
getData(...args:any[]) {
console.log(args)
console.log('我是getData中的方法')
}
}
var http:any = new HttpClient()
// http.run()
http.getData('haha', 123)
/**
* 方法参数装饰器
*/
function logParams(params:any) {
return function (target: any, methodName: any, paramsIndex: any) {
console.log(params)
console.log(target) // 对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象
console.log(methodName) // 方法的名字
console.log(paramsIndex) // 参数在函数参数列表中的索引
}
}
class HttpClient{
public apiUrl: string | undefined
constructor() {
}
getData(@logParams('xxxx') uuid:any) {
console.log(uuid)
}
}
var http = new HttpClient()
http.getData(1)
/**
* 装饰器执行的顺序
*/
function logClass1() {
return function() {
console.log('类装饰器1');
}
}
function logClass2() {
return function() {
console.log('类装饰器3');
}
}
function logAttribute() {
return function(target: any, attrName: any,) {
console.log('属性装饰器');
}
}
function logMethod() {
return function(target: any, attrName: any, desc: any ) {
console.log('方法装饰器');
}
}
function logParams1(params:any) {
return function (target: any, methodName: any, paramsIndex: any) {
console.log('方法参数装饰器1');
}
}
function logParams2(params:any) {
return function (target: any, methodName: any, paramsIndex: any) {
console.log('方法参数装饰器2');
}
}
@logClass1('aaa')
@logClass2('bbb')
class HttpClient{
@logAttribute()
public apiUrl: string | undefined
constructor() {
}
@logMethod()
getData(@logParams1('xxxx') attr:any, @logParams2() uuid:any) {
console.log(uuid)
}
}
var http = new HttpClient()
http.getData('kkkk','kjkkjlklk')