做者首先給了個咱們一個處理事件的方法。看起來也沒啥倆樣,不事後來給出的優化方法很值得學習: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。在將元素顯示在頁面裏以前先用這倆個屬性給它作定位。函數
儘管這段代碼開起來很是簡單且沒有什麼問題,但其實是很差的寫法,由於這種作法有其侷限性。學習
首先,這段代碼的應用邏輯(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); });
上述代碼還存在一個問題:即event對象被無節制地分發。event對象上包含不少的和事件相關的額外信息,而這段代碼只用到了其中倆個而已。code
做者提供了倆個理由:對象
最佳的辦法是讓事件處理程序使用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產生依賴,進而在不少地方均可以輕鬆地使用相同的業務邏輯,包括寫測試代碼。