Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

你学废了吗?——装饰器 #71

Open
george-es opened this issue Nov 23, 2020 · 0 comments
Open

你学废了吗?——装饰器 #71

george-es opened this issue Nov 23, 2020 · 0 comments
Labels

Comments

@george-es
Copy link
Owner

装饰器有以下几种类型

  • 类装饰器

  • 方法装饰器

  • 属性装饰器

  • 参数装饰器

类装饰器

有两种应用场景,默认都会有一个参数,该参数指向当前类

普通装饰器(无法传参)

无返回值

// 定义一个函数
function ClassDecorator(params: any) {
	console.log(params)  // 当前类 TestClass
	params.prototype.name = 'george'  // 修改类的 name 属性
}

@ClassDecorator // 调用类装饰器
class TestClass() {
	name: string
	constructor() {
		console.log(this.name)  // george
	}
} 

装饰器工厂(可传参)

返回一个函数

// 定义一个函数
function ClassDecorator(params: any) {
	console.log(params) // 装饰器后面的参数 hello
	return function(type) {
		console.log(type) // 类 TestClass
		type.prototype.name = 'george'
	} 
}

@ClassDecorator('hello') // 调用类装饰器
class TestClass() {
	name: string
	constructor() {
		console.log(this.name)  // george
	}
} 

使用装饰器工厂模式,我们可以重载构造函数

function LDecorator(target) {
	return class extends target {
		url: '修改后',
		getData() {
			this.url = this.url + '---'
			console.log(this.url)
		}
	}
}

@LDecorator
class L {
	public url: string | undefined;
	constructor() {
		this.url = '我是构造函数 url'
	}
	getData() {
		console.log(this.url)
	}
}

var l = new L()
l.getData()

属性装饰器

接收两个参数

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  • 方法名

返回值:函数

function propertyDecorator(params) {
    return function(target: any, attr: any) {
    	target[attr] = params
        console.log(target, attr)
    }
}

class PropertyClass {
    @propertyDecorator('http')
    public url: any | undefined;
    constructor() {}
    getData() {
        console.log(this.url)
    }
}

const p = new PropertyClass();
p.getData()

方法装饰器

接收三个参数

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  • 方法名
  • 成员的属性描述符

作用:会被应用到方法的属性修饰符上,用来监视,修改或者替换方法定义。

返回值:函数

function waysDecorator(params) {
	return function(target: any, methodName: any, desc: any) {
		console.log(target)
		console.log(methodName)
		console.log(desc)
		target.apiUrl = 'xxx'
		target.run = function() {
			console.log('run')
		}
	}
}

class WayClass {
	public url: any | undefined;
	constructor() {}
	@get()
	getData() {
		console.log(this.url)
	}
}

var w = new WayClass()
console.log(w.apiUrl)
w.run()

方法参数装饰器

接收三个参数

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  • 方法名
  • 参数在函数参数列表中的索引,从 0 开始

作用:只能用来监视一个方法的参数是否被传入,可以使用参数装饰器为类的原型增加一些元素数据

返回值:会被忽略

function WapParamsClassDecorator(params: any) {
	return function(target: any, methodName: any, paramsIndex: any) {
		console.log(params)
		console.log(target)
		console.log(methodName)
		console.log(paramsIndex)
		target.apiUrl = params
	}
}

class WapParamsClass {
	url: any | undefined;
	constructor() {}
	getData(@WapParamsClassDecorator('xxxx') uuid: any) {
		console.log(uuid)
	}
}

const w = new WapParamsClass()
w.getData(123213)
console.log(w.apiUrl)

装饰器顺序

属性 > 方法 > 方法参数 > 类

如果有多个同样的装饰器,会执行后面的

function logClass1(params:string){
    return function(target:any){
      console.log('类装饰器1')
    }
}

function logClass2(params:string){
    return function(target:any){
      console.log('类装饰器2')
    }
}

function logAttribute1(params?:string){
    return function(target:any,attrName:any){
      console.log('属性装饰器1')
    }
}

function logAttribute2(params?:string){
    return function(target:any,attrName:any){
      console.log('属性装饰器2')
    }
}

function logMethod1(params?:string){
    return function(target:any,attrName:any,desc:any){
      console.log('方法装饰器1')
    }
}
function logMethod2(params?:string){
    return function(target:any,attrName:any,desc:any){
      console.log('方法装饰器2')
    }
}



function logParams1(params?:string){
    return function(target:any,attrName:any,desc:any){
      console.log('方法参数装饰器1')
    }
}

function logParams2(params?:string){
    return function(target:any,attrName:any,desc:any){
      console.log('方法参数装饰器2')
    }
}



@logClass1('http://www.itying.com/api')
@logClass2('xxxx')
class HttpClient{
    @logAttribute1()
    @logAttribute2()
    public apiUrl:string | undefined;
    constructor(){
    }

    @logMethod1()
    @logMethod2()
    getData(){
        return true;
    }

    setData(@logParams1() attr1:any,@logParams2() attr2:any,){

    }
}

var http:any=new HttpClient();

答案:

属性装饰器2
属性装饰器1
方法装饰器2
方法装饰器1
方法参数装饰器2
方法参数装饰器1
类装饰器2
类装饰器1

@george-es george-es added the ts label Nov 23, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant