【问题标题】:Angular - how to use a utility function from a templateAngular - 如何使用模板中的实用程序函数
【发布时间】:2021-09-02 19:47:46
【问题描述】:

我有一个 Helper 类,它定义了一个静态方法“keyDown”,它获取按下的键。

我在几个组件中使用它,它只是定义为组件类上的一个方法,从模板中调用,如下所示:

     <input type="number"
       ...
       (keydown)="keyDown($event)"
       pattern="^(\d?[0-9]|[1-9]0)$"
       required/>

但是复制那个代码不好,所以我把它放到一个静态类中,如this question中解释的那样

export abstract class Helper {
  public static keyDown($event: any) {...}
}

组件:

import { Helper } from '../../../utils/helper';

  constructor(
    private helper: Helper,
  ) { }

  get keyDown(v) { return Helper.keyDown(v); }

这不起作用,因为您无法将值传递给 getter。

那么我怎样才能拥有一个从不同组件的模板中调用的共享实用程序函数呢?

更新 - 我试过了。

感谢@CharlesBarnes 的评论。这几乎奏效了!

我做了 3 个微妙但重要的改变:

  1. 类方法不再是静态的:
    export abstract class Helper {
      public keyDown($event: any) {...}
    }
  1. 注入的帮助器不再是私有的,而是公共的。这意味着模板现在可以查看助手类中的所有方法,因此可以直接调用它们:
    import { Helper } from '../../../utils/helper';
    
      constructor(
        public helper: Helper,
      ) { }
  1. 最后我更改了模板,在方法调用前加上注入类的名称(小写“helper”):
     <input type="number"
       ...
       (keydown)="helper.keyDown($event)"
       pattern="^(\d?[0-9]|[1-9]0)$"
       required/>

但它会抛出一个

NullInjectioNError, no provider for 'Helper'

:(

这种方式意味着将 Helper 类转换为服务,并使其可注入。

...但是提供一些通用帮助工具似乎有点过头了。

【问题讨论】:

  • 将getter改成常规方法getKeyDown(v)能解决问题吗?
  • @user776686 只是部分......模板必须调用它,所以每个组件都需要添加该常规方法,然后调用类上的静态方法,传递它传递的值从模板。我希望避免这种双跳。
  • 您可以创建自己的指令来包装/替换keyDown
  • 您将通过将 Helper 类的 keyDown 方法更改为非静态成员来避免双跳。然后在模板中你只需调用 helper.keyDown()

标签: angular


【解决方案1】:

这是一个很好的开始。您已接近解决方案。

到目前为止,您只声明了一个abstract 类,现在需要由另一个可以实例化的类来实现。

@Injectable()
export class MyHelper implements Helper {
  keyDown(e: KeyboardEvent){
    console.log(e)
  }
}

现在可以提供课程了。我会在组件级别上这样做:

import { Component } from '@angular/core';
import { Helper } from './helper';
import { MyHelper } from './my-helper';

@Component({
  ...
  providers: [
    { provide: Helper, useClass: MyHelper }
  ]
})
export class AppComponent  {
  constructor(
    public helper: Helper,
  ) { }
}

HTML 保持原样。

(keydown)="helper.keyDown($event)"

我会说这实际上是一个很好的模式,因为另一个组件可能使用不同的 keydown 处理程序实现。这样可以在通过抽象类进行强类型化时保持代码解耦。

【讨论】:

  • 谢谢,但这不起作用。 Angular 仍然抱怨“助手”没有注入器。所以你需要添加@Injectable。您已在组件级别添加了提供程序。这意味着需要大量代码来注入一个简单的辅助函数。我也可以将它实现为服务并在模块级别提供它,而不是每个组件(尽管我同意你的观点,处理程序的不同实现最好在组件级别提供)。更少的代码,更少的工作。所以我的问题的简短回答基本上是“你不能,你需要提供服务”;)
  • MyHelper 不调用 Helper.onKeyDown() => 它只是登录到控制台。但我应该指出,如果您添加return Helper.onKeyDown(e) // call the base method,那么当在模块级别提供 myHelper 时,Angular 会抱怨“Helper.onKeyDown 不是函数”。因此,您必须按照您的建议在组件级别提供它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-27
相关资源
最近更新 更多