在写业务的时候经常需要订阅事件和取消订阅事件,通常是用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 nbsp;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 19cm 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 |