2016-10-29 42 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)); 

也就是說,使用奧裏利亞的事件聚合您的解決方案是爲你的使用情況更加適合和更具擴展性。我想我會發布這個答案來解決原來的問題,這只是一個功能範圍問題。

相關問題