使用特定回调添加通用事件侦听器

时间:2016-10-29 13:52:50

标签: javascript jquery javascript-events aurelia

在Aurelia viewmodel组件中,我有以下JQuery代码,可以在模态可见时捕获Ctrl + S或Ctrl + Enter并调用save函数:

$(window).bind('keydown', function(event) {
  if (event.ctrlKey || event.metaKey) { // Ctrl + ___
    if ((event.which == 83) || (event.which == 115) || (event.which == 10) || (event.which == 13)) {  // Ctrl+Enter or Ctrl+S
      // Save button
      event.preventDefault();
      if ($(self.edit_calendar).is(':visible')) {
        self.saveCalendar();
      }
    }
  }
});

但是,我预计会在40多个视图模型中添加类似的功能,并且这看起来并不干净,并且为每个视图模型添加了一些丑陋的代码。我想在单例类中创建一个通用的addEventListener函数,以便从我的每个视图中轻松调用。这就是我的想法:

addListenerSave(visible, callback) {
  // Add an event listener to redirect keyboard shortcuts to specific actions
  console.log("addListenerSave()");
  $(window).bind('keydown', function(event) {
    if (event.ctrlKey || event.metaKey) { // Ctrl + ___
      if ((event.which == 83) || (event.which == 115) || (event.which == 10) || (event.which == 13)) {  // Ctrl+Enter or Ctrl+S
        // Save button
        event.preventDefault();
        if ($(visible).is(':visible')) {
          console.log("Keyboard shortcut: Save");
          callback();
        }
      }
    }
  });
}

然后,在我的各个组件中,我只需要在实例化时使用以下代码(在附件()组件生命周期中):

this.config.addListenerSave(this.edit_calendar, this.saveCalendar);

然而,这不起作用。 saveCalendar()被调用但可能来自另一个范围/上下文,所以我在saveCalendar中得到一个错误,说明"无法读取属性' selectedId'未定义"。这是指saveCalendar()代码if (this.selectedId)...。我做错了什么?

最后,当我的Aurelia组件分离时,我是否还应该删除此事件侦听器?怎么样?

我的另一个想法是使用Aurelia的eventAggregator创建一个全局事件监听器,它始终监听Ctrl + S / Ctrl + Enter,然后发布可以在每个组件中订阅的消息。

2 个答案:

答案 0 :(得分:1)

要回答原始问题,您已走上正轨 - 但由于JavaScript中this的语义,您需要绑定您的功能。 (如果您来自C#视角,那么认为JavaScript中的所有函数本质上都是扩展方法可能会有所帮助;因此,传递函数可能非常强大。)因为它很容易错过新的ES6类语法。

这可以缓解您的问题:

this.config.addListenerSave(this.edit_calendar, this.saveCalendar.bind(this));

也就是说,使用Aurelia的Event Aggregator的解决方案更适合您的用例并且更具可扩展性。我以为我发布这个答案来解决原始问题,这只是功能范围问题。

答案 1 :(得分:0)

我成功实现了添加全局事件侦听器的备用解决方案,该侦听器使用Aurelia的EventAggregator来共享Ctrl + S / Ctrl + Enter。原始问题仍然存在,但也许它不是最好的方法。这是我的解决方案:

config.js (全球单身人士)

@inject(EventAggregator)
export class Config {
  constructor(eventAggregator) {
    var self = this;
    this.eventAggregator = eventAggregator;
    // listen for Ctrl+S or Ctrl+Enter and publish event
    window.addEventListener("keydown", function(event) {
      if (event.ctrlKey || event.metaKey) { // Ctrl + ___
        if ((event.keyCode == 83) || (event.keyCode == 115) || (event.keyCode == 10) || (event.keyCode == 13)) {  // Ctrl+Enter or Ctrl+S
          // Save button
          console.log("Publishing ewKeyboardShortcutSave...");
          event.preventDefault();
          self.eventAggregator.publish('ewKeyboardShortcutSave', true);
        }
      }
    });
  }
}

然后,在我的组件viewmodel calendar.js

@inject(EventAggregator)
export class Calendar {
  constructor(eventAggregator) {
    this.eventAggregator = eventAggregator;
  }
  attached() {
    var self = this;
    // Ctrl+Enter is save
    this.eventAggregator.subscribe('ewKeyboardShortcutSave', response => {
      console.log("I heard ewKeyboardShortcutSave: " + response);
      if ($(self.edit_calendar).is(':visible')) {
        self.saveCalendar();
      }
    });
  }
}

像魅力一样工作,现在我可以自由添加更多组件事件监听器,甚至可以扩展功能,为Ctrl + F(用于查找)等添加全局监听器。