导读:这是在学习ts时,对es7中装饰器的学习,所以用到一些ts语法。
装饰器是什么
在学习一个知识前,得先了解它,它是什么,它有什么用。
装饰器是一种特殊的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为。
通俗讲,装饰器就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能。
我对装饰器分类是这样的:
装饰器:类装饰器、属性装饰器、方法装饰器、方法参数装饰器
类装饰器:普通饰器(无参数传递)
装饰器工厂(有参数传递)
类装饰器
普通装饰器
function decoratorHttp(target: any) {
console.log(target, 'HttpClient 构造函数');
target.prototype.url = 'https://juejin.cn';
}
@decoratorHttp // 注意这里别加 ; (分号)
class HttpClient {
constructor() {
}
getData() {
}
}
let httpC: any = new HttpClient();
console.log(httpC.url); // https://juejin.cn
装饰器工厂
function decoratorHttp(params: string) {
return function(target: any) {
console.log(params, '参数'); // xxx 参数
console.log(target, 'HttpClient 构造函数');
target.prototype.url = 'https://juejin.cn';
}
}
@decoratorHttp('xxx')
class HttpClient {
constructor() {
}
getData() {
}
}
let httpC: any = new HttpClient();
console.log(httpC.url); // https://juejin.cn
属性装饰器
function decoratorAttr (params: string) {
return function(target: any, attrName: string) {
console.log(params, '参数');
// 对于 static 静态成员来说,target 是构造函数
// 对于 public 实例成员来说,target 是原型对象
console.log(target, 'HttpClient');
console.log(attrName, '属性名'); // url 属性名
// 可以修改属性
target[attrName] = 'www.bilibili.com';
}
}
class HttpClient {
@decoratorAttr('public');
public url: string | undefined;
@decoratorAttr('static');
static url: string | undefined;
constructor() {
}
getData() {
console.log(this.url);
}
}
let httpC = new HttpClient();
httpC.getData(); // www.bilibili.com
方法装饰器
function decoratorMethod(params: string) {
return function(target: any, methodName: string, desc: any) {
console.log(params, '参数');
console.log(target, '原型对象');
console.log(methodName, '函数名');
console.log(desc, '描述对象');
console.log(desc.value, '方法');
let methodLoad = desc.value;
desc.value = function(...arg: Array<any>) {
methodLoad.apply(this, arg); // 这里继承原来的方法
// 可以修改方法
arg = arg && arg.map((item: any) => {
return String(item);
})
console.log(arg, 'decorator---arg'); // ["123", "xxx"] "decorator---arg"
}
}
}
class HttpClient {
public url: string | undefined;
constructor() {
}
@decoratorMethod('xxx')
getData(...arg: Array<any>) {
console.log(arg, 'HttpClient---arg'); // [123, "xxx"] "HttpClient---arg"
}
}
let httpC = new HttpClient();
httpC.getData(123, 'xxx');
方法参数装饰器
function decoratorParam(params: string) {
return function(target: any, methodName: string, paramIndex: number) {
console.log(params, '参数');
console.log(target, '原型对象');
console.log(methodName, '函数名');
console.log(paramIndex, '参数下标');
// 可以操作属性
target.url = 'www.bilibili.com';
}
}
class HttpClient {
public url: string | undefined;
constructor(){
}
getData(@decoratorParam('xxx') info: string) {
console.log(info + this.url);
}
}
let httpC = new HttpClient();
httpC.getData('url: ');
类修饰器、属性修饰器、方法修饰器、方法参数修饰器执行时机
function _classDecorator1 (params1: any) {
return function(target: any) {
console.log(params1 + '类装饰器1');
}
}
function _classDecorator2(params2: any) {
return function(target: any) {
console.log(params2 + '类装饰器2');
}
}
function _attributeDecorator1(params: any) {
return function(target: any, attrName: any) {
console.log(params, '属性装饰器1');
}
}
function _methodDecorator1(params: any) {
return function(target: any, methodName: any, desc: any) {
console.log(params, '方法装饰器1');
}
}
function _methodDecorator2(params: any) {
return function(target: any, methodName: any, desc: any) {
console.log(params, '方法装饰器2');
}
}
function _methodParamsDecorator1(params: any) {
return function(target: any, methodName: any, paramsIndex: number) {
console.log(params, '方法参数装饰器1');
}
}
function _methodParamsDecorator2(params: any) {
return function(target: any, methodName: any, paramsIndex: number) {
console.log(params, '方法参数装饰器2');
}
}
@_classDecorator1('_classDecorator1')
@_classDecorator2('_classDecorator2')
class HttpClient {
constructor() {
}
@_methodDecorator1('_methodDecorator1')
@_methodDecorator2('_methodDecorator2')
getData(@_methodParamsDecorator1('_methodParamsDecorator1') uin: string, @_methodParamsDecorator2('_methodParamsDecorator2') info: string) {
console.log('getData');
}
@_attributeDecorator1('_attributeDecorator1')
public url: string | undefined;
setData(@_methodParamsDecorator1('_methodParamsDecorator1') uin: string, @_methodParamsDecorator2('_methodParamsDecorator2') info: string) {
console.log('setData');
}
}
/*
_methodParamsDecorator2 方法参数装饰器2
_methodParamsDecorator1 方法参数装饰器1
_methodDecorator2 方法装饰器2
_methodDecorator1 方法装饰器1
_attributeDecorator1 属性装饰器1
_methodParamsDecorator2 方法参数装饰器2
_methodParamsDecorator1 方法参数装饰器1
_classDecorator2类装饰器2
_classDecorator1类装饰器1
*/
总结下:
从上向下执行修饰器
在方法中: 方法参数修饰器
方法修饰器
最后执行类修饰器
有多个时,后写的先执行