请教一下 TypeScript 装饰器的用法 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
sunny1688
V2EX    程序员

请教一下 TypeScript 装饰器的用法

  •  
  •   sunny1688 2023-08-04 17:53:32 +08:00 2164 次点击
    这是一个创建于 807 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • 在写业务的时候经常需要订阅事件和取消订阅事件,通常是用emitter.onemitter.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 条附言    2023-08-05 19:34:12 +08:00
    搞定了,要使用 装饰器 Stage-3 版本,我提供的代码是 Stage-1 版本,关于 Stage-3 版本可以看 #4 楼提供的链接
    14 条回复    2023-08-06 14:47:06 +08:00
    kevin97
        1
    kevin97  
       2023-08-04 18:13:30 +08:00
    这样试试呢?添加 bind

    ```js
    // 直接这样绑定可以运行
    emitter.on(eventName, descriptor.value.bind(target));
    ```
    sunny1688
        2
    sunny1688  
    OP
       2023-08-04 18:18:32 +08:00
    target 不是 Logic 实例 @kevin97
    NICE20991231
        3
    NICE20991231  
       2023-08-04 18:50:46 +08:00
    方法装饰器负责添加元信息(就是一个配置...),具体的由 class 装饰器实现,可以试下
    zbinlin
        4
    zbinlin  
       2023-08-04 18:59:25 +08:00
    zsj1029
        5
    zsj1029  
      nbsp;2023-08-04 21:07:51 +08:00 via iPhone
    Ts 的装饰器还是实验阶段吧,没正式发布吧
    hsfzxjy
        6
    hsfzxjy  
       2023-08-04 21:46:57 +08:00
    帮楼主一整套写好了

    https://www.typescriptlang.org/play?experimentalDecorators=true&target=99#code/MYewdgzgLgBAogNwKZigYQIYBssCMPADWAshgA4DSSAnjALwwDK1AtriFgBQCUA3AFBRqZJPGSpMOfEVJl6MWQB5oAJwCWYAOYAaGADEArmGBQ14ANoBdAHwD+oSLHDzOScVAByGFkgBcMVQ1NbnprGE4oDBVNJCh-AHlcACskE10fKAALEAATLx9-QK1dHKQIYHUyKBAVfwAFFRARFSEAETKKtSqakLowgG9+GGGYB2gYQiwMCAh5SOjYmGmYI0IwEAB3MCXZ-phzRBR0bDwCEnIqakt-Q4kT6XO5AF8BEZgsReBcWRv3SVOZORXiM1AAzcKJFImAB0mWm8S2nEm0wguluxykZ1kl24IUGbzeX1k8mRMwOf3uWIuNEswOGTxgSCwEFE+IJwyJ5HkYCQGwUQKG7JgkNSUGhpVBGiQDSaSBa1CRUxmaIpmMBlBoujZQpGDklmgMKgwuA+-lB2BZ2kFOuGKAMPiNJr8MHNzKQVptIwQ2AMzs5ZGtBKe3EDT0DY1gX1mDH90JiUFc7nySBCAH5U-taeHcBBoWQDBBMpxSuVKtUVNDvVhfXxs7JoSyE24jsndFHa2H7OBxgAlJCaNTQOVIHL-B4QS7yZhsDg8ARCEQwPsDocqEdjs7R-bN1DJwpQdTFUa4fyGYymcCWKwCUFGExmbZrldQOUAQRw6IgnBAyX8GDA1C6E+g4vmutThGA3jOkUOgumAp53heYC9GECAgGoOR4oGYIQskoqwvCiI-kkujLiBw6jpSRATjQuIwGuUCGmAdKjN2sDAauI7+GRnGUWqhBbtega3ueD4wHCYA5B8MrVAuSCcAAHn+AFYTqEYwGQjTVPIIowvGMkgHJ8SgoptY6jhnCaYZID0HQDBgAYOAhAxTEsW8ElSdKWmGcI8lWdUZlChZACEulinCEAImAlneSqRwbuqOLObErmBoSbHHj8YjxVRjzyP5IDkjl-HYjSbm6t85DQqCNRwAQRacFGug7p4UEoceuY1SodXAEWXyhDA2o2up7BGDk8hfNCuAaDk37JIFnocaBcqJi2UG6KNkkLTaS0UXmBZFuYLWtjAm05JY21vMG21hu5-6eQZclzUk21heKSCSjyMrNEIz2kf25FrnxAICZcWppSMdoOsapouha7oQxy4D6oaMPOq6lqIzAVa+v4u1Ax6IzBvwnYifezhGPj75YJ+z3KYBKxgPjcr+JwkEFAEB5BG2J76IhD7tWhGGqbqGXMzk3EA7xCUCfIxHmDxy3A+OlxZm84vVbV9WcJw5js+6x4XQNlNS8tKhs+tx64ixGsfFoWTyAADAInbAEqswAEKDYGmlqN6L70UgGA5OAWC0DjogMAATM7gYAALgJwABELWvknIZvKCACMPDe2p3YcEg0JYCAmjJx7lY+pHSe6Fkg615kg6V9WKYsWGrvuzAaCMgpL6SZ7ecjL7-uiGuweh+HVdR-IAAsUcsQn0Up+4acZyMoJR7nQ3pZAhfF6XydoM3vrT3QNcwHXuYR1HN0k-w-Bk0hgfPsO5vHVB+6HrBXwIaJ4Ai8MAA9IAmAgBCK0APtGgBouUAG9ygALm0ADGK4YC4fH3mXAABorCiMBFAABJ+iTX1k8MIXVGTuBgEnPB78fBPCTmgteQCQEQJgYAYBjAAUrkg3eKCS7oIAJJgDQoQIIMA8EEKgk8aEEi6HZh4HfB+-MKZM1Nq-Vau4P6cy-jzX+5NkKDwYWAqBcDAAAqRwiAe9uGcDQQAVUUS-IG2CRG4GhIQ4hNRSFHHIZQpMYjaEhk7F2ThRdzEAHIAC0YSwlBJDCNbkvIYAewEFTD87gvy4CAkosCtYTa2OprTVJjNmYqFrGMMxB9QnhJCZE-x4xgAxL5GgBJ6ScnJMamk2xcpMk2MBk0o4X5gC6CyYDdpAhilcNKeUip3AgA
    hsfzxjy
        7
    hsfzxjy  
       2023-08-04 21:50:34 +08:00
    @hsfzxjy 如果你想在构造时就自动注册,那就在构造函数里手动调用一下 registerAllEvents
    yetrun
        8
    yetrun  
       2023-08-05 14:35:33 +08:00
    装饰器尚在试验阶段,没有大规模铺开来用,别用。尤其是自己发布的包或者项目,别用,可能过几年就用不了了。
    zjccc
        9
    zjccc  
       2023-08-05 15:47:21 +08:00
    装饰器是作用在原型链上的,所以拿不到 this 。
    可以使用装饰器配合 Reflect-metadata 添加元数据(本质上和上面搞一个全局的 map 差不多),然后构造函数里面通过 this 拿到 prototype 上的方法,再调用 .call(this)
    19cm
        10
    19cm  
       2023-08-05 21:41:26 +08:00
    别用二货玩意,都要被淘汰的玩意
    hzzhzzdogee
        11
    hzzhzzdogee  
       2023-08-05 22:46:25 +08:00
    angular 不是大规模使用装饰器吗, 这个语法还是稳定的吧?
    nzbin
        12
    nzbin  
       2023-08-05 23:33:50 +08:00
    @hzzhzzdogee Angular 的装饰器只是语法糖,主要用于传递元数据,编译之后是没有的
    sunny1688
        13
    sunny1688  
    OP
       2023-08-06 14:46:05 +08:00
    @hzzhzzdogee
    @tianzi123

    正如 12 楼说的那样,装饰器只是语法糖,那些 @符号编译后是没有的,现在都 stage-3 阶段了,不会淘汰的
    sunny1688
        14
    sunny1688  
    OP
       2023-08-06 14:47:06 +08:00
    @hsfzxjy 很感谢!

    不过还是没有达到我想要的版本,我用 stage-3 版本实现好了,只需要 @on('xx') 就能自动订阅事件,不需要在构造函数里面手动注册
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     914 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 19:08 PVG 03:08 LAX 12:08 JFK 15:08
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86