【问题标题】:Attach a class method to window object using decorators使用装饰器将类方法附加到窗口对象
【发布时间】:2023-04-04 07:24:01
【问题描述】:

我正在使用带有 typescrpit 的 VueJS,但这可以在任何 js 框架中。

我有一些想要全局公开的方法的组件,以便可以通过浏览器控制台使用它们。第一个想法是将它们附加到窗口对象。这可以通过我们安装在我的案例中的生命周期方法来完成,但我更喜欢使用装饰器来编写和使用更简洁的解决方案。

我尝试过类似的方法:

mycomponenet.ts:

function makeGlobal() {
   return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
     (window as any)[propertyKey] = () => target[propertyKey]();
   };
 }

那么这个装饰器将很容易使用:

@makeGlobal()
myMethodToGoGloabl(){
// do stuff ...
}

直到现在一切正常,直到函数使用 "this" 像:

@makeGlobal()
myMethodToGoGloabl(){
  this.firstName = "";
}

然后我得到一个未定义的错误 firstName。通过搜索和阅读,我了解到装饰器是在类实例化之前执行的,因此我暴露的(如果我弄错了,请纠正我)是一个原型方法,而不是我们无法访问它的实例方法。我尝试过 bind(this) 但失败的原因与我没有在全局范围内公开实例的方法相同。

有没有办法在我的情况下使用装饰器,或者它们在这里没用?

【问题讨论】:

  • 所以你想让每个全局方法都让函数的实例保持活动状态?
  • 也许这可以在 Vue 中完成,但不能在其他框架中完成,因为 Vue 提供了一些钩子来修改组件实例属性
  • 通过阅读您的代码,它应该可以按预期工作。请在线创建一个工作示例,然后我们可以找出确切的原因。
  • 我认为使用装饰器是个坏主意。您必须确保您的属性名称只有一个,并且一旦您的组件死亡,您可能会遇到垃圾收集器的一些问题。但是如果它是一个单例并且它会永远离开那么它是可以做到的。

标签: javascript typescript decorator


【解决方案1】:

猜猜问题出在你的装饰师上。你根本没有接管这个实例...... 而且你这样做的方式,你将无法传递参数。

建议:

function makeGlobal() {
   return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
     var currentThis = this;
     (window as any)[propertyKey] = () => target[propertyKey].apply(currentThis, args);
   };
 }

还要记住克里斯蒂安在评论中所说的话。它基本上只能用于单例,因为它会覆盖多个实例的方法

【讨论】:

  • 我不明白这个解决方案是如何工作的,currentThis 不是指组件实例
  • 你不需要将'this'绑定到实例方法,因为它已经存在了。
猜你喜欢
  • 2010-11-28
  • 2014-01-14
  • 2020-01-11
  • 1970-01-01
  • 2012-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-22
相关资源
最近更新 更多