类装饰器顾名思义是对类的内容进行修饰,在Typescript 类其实就是对象,这样配合原型对象操作可以达到操作类的目的。
首先看下类装饰器在TS中的定义:
declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
案例思路描述:
我们用组合的思想,可以将弹钢琴的技能部分单独实现出来,谁想拥有引入即可。
装饰器相同的道理,只需要实现这个装饰器即可,下面用代码实现。
const musicDecorator : ClassDecorator = (target:Function)=>{
target.prototype.playPiano = () => {
console.log('弹钢琴');
}
}
@musicDecorator
class Student {
}
@musicDecorator
class Artist{
}
var xiaoming = new Student();
(<any>xiaoming).playPiano()
var jay = new Artist();
(<any>jay).playPiano()
控制台输出:
类装饰器其实就是一个语法糖,类装饰器相当于一个函数,函数的参数是类构造函数。
那么上面的例子我们完全可以这么写,输出结果一致:
const musicDecorator : ClassDecorator = (target:Function)=>{
target.prototype.playPiano = () => {
console.log('弹钢琴');
}
}
class Student {
}
class Artist{
}
//函数调用
musicDecorator(Student)
musicDecorator(Artist)
var xiaoming = new Student();
(<any>xiaoming).playPiano()
var jay = new Artist();
(<any>jay).playPiano()
有些装饰器需要参数判断情况,比如学生和艺术家都能弹钢琴,但是弹的曲目不一样,那么需要带参数判断,工厂根据参数创造出装饰器返回。
代码思路:
下面看代码例子:
const musicDecorator:(song:string)=> ClassDecorator = (song)=>{
return (target:Function)=>{
target.prototype.playPiano = () => {
console.log(song);
}
}
}
@musicDecorator('小星星')
class Student {
}
@musicDecorator('小夜曲')
class Artist{
}
var xiaoming = new Student();
(<any>xiaoming).playPiano()
var jay = new Artist();
(<any>jay).playPiano()
控制台输出:
类装饰器和函数一样是可以叠加的,一般是可以这么想象的。
如下面的例子:(学生既可以弹钢琴,又有班级属性)
const musicDecorator:(song:string)=> ClassDecorator = (song)=>{
return (target:Function)=>{
target.prototype.playPiano = () => {
console.log(song);
}
}
}
const classNameDecorator:ClassDecorator = (target:Function)=>{
target.prototype.className = '三年二班'
}
@musicDecorator('小星星')
@classNameDecorator
class Student {
}
var xiaoming = new Student();
(<any>xiaoming).playPiano()
console.log((<any>xiaoming).className);
验证案例思路:
示例代码:
const musicDecorator:ClassDecorator = (target:Function)=>{
console.log('执行musicDecorator');
console.log(target.prototype.className);
target.prototype.song = '小星星'
}
const classNameDecorator:ClassDecorator = (target:Function)=>{
console.log('执行classNameDecorator');
console.log(target.prototype.song);
target.prototype.className = '三年二班'
}
@classNameDecorator
@musicDecorator
class Student {
}
打印结果:
结论:
装饰器嵌套相当于 函数嵌套,先执行后面的装饰器,当后面的装饰器执行完,才执行前面的。