2016-10-29 43 views
0

在奥里利亚视图模型组件,我有以下的jQuery代码,致力于捕捉Ctrl + S键或Ctrl + Enter键,而一个模式是可见的,并调用保存功能:添加通用事件侦听器与特定的回调

$(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中出现一个错误,提示“Can not read property'selectedId'of undefined”。这是指saveCalendar()代码if (this.selectedId)...。我究竟做错了什么?

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

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

+0

由于事件处理程序绑定到窗口,你不是只需要一个事件处理程序,或者你有40多个窗口吗? – adeneo

+0

是的,只有一个事件侦听器是有意义的,但是我需要回调根据当前可见的组件而不同。所以,我在不同的时间基本上需要一个不同的事件监听器函数。所以我的问题依然存在... – LStarky

回答

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); 
     } 
     } 
    }); 
    } 
} 

然后,我的组件视图模型内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添加全局监听器(用于查找)等。

1

为了回答你原来的问题,你在正确的轨道上 - 但由于JavaScript中的this的语义,你需要绑定你的函数。 (如果你是从C#的角度来看,可能会认为JavaScript中的所有函数本质上都是扩展方法;因此,传递函数可能非常强大。)由于新的ES6类语法,很容易忽略它。

这应该工作,以减轻您的问题:

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

也就是说,使用奥里利亚的事件聚合您的解决方案是为你的使用情况更加适合和更具扩展性。我想我会发布这个答案来解决原来的问题,这只是一个功能范围问题。

相关问题