首页 文章

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

提问于
浏览
0

在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中得到一个错误,表示"Cannot read property 'selectedId' of undefined" . 这是指saveCalendar()代码 if (this.selectedId)... . 我究竟做错了什么?

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

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

2 回答

  • 1

    我成功实现了添加全局事件侦听器的备用解决方案,该侦听器使用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(for find)等添加全局监听器 .

  • 0

    为了回答你原来的问题,你走在正确的轨道上 - 但是由于JavaScript中 this 的语义,你来自C#的观点,它可能有助于认为JavaScript中的所有函数本质上都是扩展方法;因此,传递函数可能非常强大 . )由于新的ES6类语法,很容易错过这个 .

    这应该可以缓解您的问题:

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

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

相关问题