使用
(1) 装饰器还在 proposal 阶段,在 react 项目中使用需要装一些依赖支持:
yarn add @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties
(2) package.json 文件中添加配置:
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
],
[
"@babel/plugin-proposal-class-properties",
{
"loose": true
}
]
]
类的装饰器
(1)语法:
const test = (target) => {
target.name1 = 'name';
target.fn = () => {};
};
// 修饰类的装饰器:相当于test(Demo)
@test
class Demo {}
console.dir(Demo);
(2)console.dir(Demo) 输出:
类的属性装饰器
(1) 语法:
const test = (target, name, descriptor) => {
/*
target:Demo.prototype
name:'x'
descriptor:{configurable: true, enumerable: true, writable: true, initializer: ƒ} 修饰的属性,则初始值是基于initializer函数设置的!!
*/
/*
target:Demo.prototype
name:'getX'
descriptor:{configurable: true, enumerable: false, writable: true, value: ƒ} 修饰的函数,则初始值是基于value属性设置的!!
*/
console.log(target, name, descriptor);
};
class Demo {
@test x;
@test
getX() {}
}
// 给类的属性设置装饰器,创建实例触发装饰器执行
let d = new Demo();
console.log(d);
(2) console.log(target, name, descriptor); 输出结果
装饰器实例
const readonly = (_target, _name, descriptor) => {
// 设置为不可修改
descriptor.writable = false;
};
// 记录函数运行所需时间
const logTimer = (_target, name, descriptor) => {
// 原来的函数
const originFn = descriptor.value;
descriptor.value = function (...params) {
console.time(name);
const res = originFn.apply(this, ...params);
console.timeEnd(name);
return res;
};
};
class DemoDecorator {
@readonly x = 100;
@logTimer
getX() {
for (let i = 0; i < 100000000; i++) {}
return this.x;
}
}
const demo = new DemoDecorator();
console.log(demo.getX());
输出结果:
总结
类和属性都可以有多个装饰器,从下到上处理;同一个装饰器也可以作用于多个对象。