Angular 6:HostListener修饰符在生产构建中失效

4
我的应用程序注册热键监听器,允许用户仅使用键盘执行操作。以下是一个示例:
  @HostListener('document:keydown.meta.a', ['$event'])
  selectAllHotkey(event: KeyboardEvent) {
    event.preventDefault();
    this.nodes = this.nodes.map(node => {
      node.is_selected = true;
      return node;
    });
  }

这个方法在组件内部,目前运行良好。然而,最近用户要求平台特定的热键(例如使用Control键代替Command键)。为了实现这一点,我创建了以下函数:

export function userAgentToggle<D>(window: Window, pcValue: D, osxValue: D): D {
  if (window.navigator.userAgent.indexOf('Mac OS X') === -1) {
    return pcValue;
  } else {
    return osxValue;
  }
}

这个函数根据用户代理返回两个参数中的一个。 我可以这样应用它:
  @userAgentToggle(
    window,
    HostListener('document:keydown.control.a', ['$event']),
    HostListener('document:keydown.meta.a', ['$event'])
  )
  selectAllHotkey(event: KeyboardEvent) {
    // ...
  }

在开发中这个很好工作。通过使用用户代理切换器,我可以验证每个平台是否被识别,并监听适当的按键。然而,在生产环境中不起作用。如果应用程序经过构建过程,则不会触发任何事件侦听器。
通常情况下,我会假设这是我的代码问题,但是它在开发环境中运行良好,这让我认为这可能是编译器错误。我是做错了什么呢?还是应该提交一个Angular bug ticket?
编辑:我尝试调整一些内容,结果出现一个错误,指出“装饰器中不支持函数调用”。通过谷歌搜索,我发现这是Angular AoT编译器的限制。我认为Angular编译器不支持此类动态行为。我解决了这个问题,只监听keydown事件,并添加了第二个装饰器,可以将其筛选到正确的按键组合。

也许我很蠢,你试过在Chrome中调试它吗?也许你可以看到dev和prod之间的区别。 - wannadream
@wannadream 我已经尝试过了,但由于生产构建都是被压缩的,所以很难做到。 - Jonah
1
@Jonah,如果你提供一个样例的StackBlitz,我会帮你解决问题。 - cgatian
@cgatian 我提交了一个错误票,并创建了一个 Stackblitz。https://github.com/angular/angular/issues/26729#issue-373608371 - Jonah
1
@Jonah 太棒了,我会看一下! - cgatian
1个回答

0
我找到的解决方案是:在顶层HTML元素标签上绑定一个keydown事件(keydown)="yourMethod($event)"

后端保持不变(使用selectAllHotkey()或任何其他方法)

原因:似乎ng build与--aot参数不适用于@HostListener(从某个版本的Angular开始)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接