讀《編寫可維護的JavaScript》第七章總結

 

第七章 事件處理

7.1 典型用法

做者首先給了個咱們一個處理事件的方法。看起來也沒啥倆樣,不事後來給出的優化方法很值得學習:app

 // 很差的寫法
         function handleClick(event) { var popup = document.getElementById("popup"); popup.style.left = event.clientX + "px"; popup.style.top = event.clientY + "px"; pop.className = "reveal"; } // 一個事件綁定事件(第5章的)
         addListener(element, "click", handleClick);

做者補充了一句:這段代碼只用到了event對象的倆個屬性:clientX和clientY。在將元素顯示在頁面裏以前先用這倆個屬性給它作定位。函數

                       儘管這段代碼開起來很是簡單且沒有什麼問題,但其實是很差的寫法,由於這種作法有其侷限性。學習

 

 7.2 規則 1:隔離應用邏輯

首先,這段代碼的應用邏輯(application logic)和用戶行爲混在一塊兒了。就是說:這個事件的處理方法和點擊事件連在一塊兒了,從而致使耦合度的提升。測試

這個狀況其餘語言中也很常見,一般咱們將處理邏輯封裝起來從而能夠把代碼重用,因此做者提出了很重要的思想:優化

將應用邏輯從全部事件處理程序中抽離出來的作法是一種最佳實踐。this

 將代碼重構一下變成這樣:spa

         // 好的寫法 - 拆分應用邏輯
         var MyApplication = { handleClick: function(event){ this.showPopUp(event); }, showPopUp: function(event) { var popup = document.getElementById("popup"); popup.style.left = event.clientX + "px"; popup.style.top = event.clientY + "px"; popup.className = "reveal"; } }; addListener(element, "click", function(event) { MyApplication.handleClick(event); });

 

7.3 規則2:不要分發事件對象

上述代碼還存在一個問題:即event對象被無節制地分發。event對象上包含不少的和事件相關的額外信息,而這段代碼只用到了其中倆個而已。code

做者提供了倆個理由:對象

  1. 方法接口並無代表那些數據是必要的。好的API必定是對於指望和依賴都是透明的。(譯者在此也加了譯註:大多數狀況並不理想,主要看第二點)。
  2. 方便測試

最佳的辦法是讓事件處理程序使用event對象來處理事件,而後拿到全部須要的數據傳給應用邏輯。blog

將代碼重構一下:

         // 好的寫法
         var MyApplication = { handleClick: function(event){ this.showPopUp(event.clientX,event.clientY); // 這裏標明所期待傳入的參數
 }, showPopUp: function(x,y) { // 這裏的參數就再也不依賴event咯
                  var popup = document.getElementById("popup"); popup.style.left = x + "px"; popup.style.top = y + "px"; popup.className = "reveal"; } }; addListener(element, "click", function(event) { MyApplication.handleClick(event); });

測試時或者代碼的任意位置都很輕易調用這段邏輯:

         // 這樣調用很是棒
         MyApplication.showPopUp(10, 10);

 

最後,當處理事件時,最好讓事件處理程序成爲接觸到event對象的惟一的函數。事件處理程序應當在進入應用邏輯以前針對event對象執行任何須要的操做,包括阻止默認事件或阻止事件冒泡,都應當直接包含在事件程序中。

         // 好的寫法
         var MyApplication = { handleClick: function(event){ // 假設事件支持DOM Level2
 event.preventDefault(); event.stopPropagation(); // 傳入應用邏輯
                   this.showPopUp(event.clientX,event.clientY); }, showPopUp: function(x,y) { var popup = document.getElementById("popup"); popup.style.left = x + "px"; popup.style.top = y + "px"; popup.className = "reveal"; } };

在這段代碼中,MyApplication.handleClick()是事件處理程序,所以它在數據傳入應用邏輯以前調用 event.preventDefault()和 event.stopPropagation(),這清楚的展現了事件處理程序和應用邏輯之間的分工。由於應用邏輯不須要對event產生依賴,進而在不少地方均可以輕鬆地使用相同的業務邏輯,包括寫測試代碼。

相關文章
相關標籤/搜索