在写业务的时候经常需要订阅事件和取消订阅事件,通常是用emitter.on
,emitter.off
来完成,如果要绑定 this 的话,会使用 emitter.on('key',this.xxx.bind(this)); 用于绑定 this
最近看到装饰器 @expression
,在想是不是可以用装饰器的方式来给某个方法自动订阅事件,但遇到了 this 指向的问题,在装饰器内无法访问到 this ,所以想请教一下各位大神应该如何实现这种想法,谢谢,下面是我的一个实现(如果不需要 this 绑定的话是可以的,但怎么可能会不要 this 绑定呢)
import EventEmitter from 'node:events';
const emitter = new EventEmitter();
const on = (eventName: string) => {
return (target: Object, methodName: string, descriptor: PropertyDescriptor) => {
// 直接这样绑定可以运行
emitter.on(eventName, descriptor.value);
const value = descriptor.value;
// 如果是这种写法,就可以有 this ,但不会执行到 get()里面,写了也没用
return {
configurable: true,
enumerable: true,
get() {
// 这里的 this 就是 Logic ,但根本不会执行到这里面
const bound = value.bind(this);
emitter.on(eventName, bound);
return bound;
}
} as PropertyDescriptor
}
}
const off = (eventName: string) => {
return (target: Object, methodName: string, descriptor: PropertyDescriptor) => {
// todo
}
}
class Logic {
value = 1;
@on('eventKey')
onStart() {
console.log('onStart');
// this 是 undefined ,我想在把 this 绑定到当前对象上,应该如何在装饰器上处理?
console.log(this); //
}
@off('start')
onDestroy() {
}
}
new Logic();
// 某些时刻会触发,这里是否模拟一下
emitter.emit('eventKey');
1
kevin97 2023-08-04 18:13:30 +08:00
这样试试呢?添加 bind
```js // 直接这样绑定可以运行 emitter.on(eventName, descriptor.value.bind(target)); ``` |
3
NICE20991231 2023-08-04 18:50:46 +08:00
方法装饰器负责添加元信息(就是一个配置...),具体的由 class 装饰器实现,可以试下
|
4
zbinlin 2023-08-04 18:59:25 +08:00
|
5
zsj1029 2023-08-04 21:07:51 +08:00 via iPhone
Ts 的装饰器还是实验阶段吧,没正式发布吧
|
6
hsfzxjy 2023-08-04 21:46:57 +08:00
|
8
yetrun 2023-08-05 14:35:33 +08:00
装饰器尚在试验阶段,没有大规模铺开来用,别用。尤其是自己发布的包或者项目,别用,可能过几年就用不了了。
|
9
zjccc 2023-08-05 15:47:21 +08:00
装饰器是作用在原型链上的,所以拿不到 this 。
可以使用装饰器配合 Reflect-metadata 添加元数据(本质上和上面搞一个全局的 map 差不多),然后构造函数里面通过 this 拿到 prototype 上的方法,再调用 .call(this) |
10
tianzi123 2023-08-05 21:41:26 +08:00
别用二货玩意,都要被淘汰的玩意
|
11
hzzhzzdogee 2023-08-05 22:46:25 +08:00
angular 不是大规模使用装饰器吗, 这个语法还是稳定的吧?
|
12
nzbin 2023-08-05 23:33:50 +08:00
@hzzhzzdogee Angular 的装饰器只是语法糖,主要用于传递元数据,编译之后是没有的
|
13
sunny1688 OP |