本文主要和大家分享關於JavaScript自訂事件詳細分析,事件就是用戶和瀏覽器交互的一種途徑,在本例中我們的代碼邏輯一般就是收集用戶填寫信息,驗證信息合法性,利用AJAX與伺服器互動,需要的朋友可以參考下,希望能幫助大家。
事件
技術一般水準有限,有什麼錯的地方,望大家指正。
事件就是使用者和瀏覽器互動的一種途徑。假如一個用戶註冊的功能,我們在填寫完基本資訊之後,點擊提交按鈕就可以實現註冊功能,而要完成這個功能所需要的就是點擊事件。我們預先定義好操作行為,在使用者點擊提交按鈕時就執行我們預先定好的行為,在本例中我們的程式碼邏輯一般就是收集使用者填寫信息,驗證資訊合法性,利用AJAX與伺服器互動。
這個過程就好像我們平時封裝函數然後調用函數一樣,事件其實也就類似函數定義函數調用這樣的一個過程,只不過事件函數的調用是由用戶的一些操作來告知瀏覽器,讓瀏覽器在去呼叫函數的。
首先瀏覽器已經給我們提供了一列的事件,包括click,keydown等等,為什麼還需要自訂事件呢?其實就是對我們的行為有更精確的描述。以上面的用戶註冊為例我們可以定義一個名為saveMessage的事件,在點擊提交按鈕時觸發這個事件,好像看起來更加直觀一些,不過這看起來和普通的函數調用沒什麼區別,仔細想了想函數呼叫和事件觸發的差別就是我們自己執行的函數就是函數調用,不是由我們執行的函數就是事件觸發。看下面的程式碼:
window.onload = function(){ var demo = document.getElementById("demo"); demo.onclick = handler; function handler(){ console.log("aaa"); } }
在我們點擊按鈕的時候就會印aaa,而且很明顯的可以看出函數並不是由我們呼叫的而是由瀏覽器來執行的,如果我們直接呼叫函數handler()一樣可以列印aaa但這是由我們呼叫的所以是函數呼叫。
自訂事件的作用
自訂事件就是我們依照瀏覽器對事件的機制來自訂的函數。自訂事件,可以對我們的處理函數帶來更好的說明,也可以為我們的插件帶來更好的處理流程。假如我們又一個這樣的需求:從伺服器端拉取一組數據然後在HTML中顯示成列表,然後標識出第一條數據,假如我們利用一個現有的處理函數,我們可能會這樣寫:
dataTable("url"); $("table").find("input[type='checkbox']:first").prop("checked",true);
這是不能達到我們目的的因為JS是單一執行緒的而AJAX是異步的,當程式碼$("table").find("input[type= 'checkbox']:first").prop("checked",true)執行的時候,我們需要的資料還沒有取得到。我們去修改插件的內部實作顯然是不明智的,一個可以被人接受的插件必然是有合理的回調函數(或者自訂事件)的,假如現在有一個列表繪製成功的回調函數,我們就可以把這個回呼函數看做是一個事件,我們可以對這個事件增加事件操作,定義好處理函數,然後在列表繪製成功時讓外掛程式來執行這個處理函數。
自訂事件實作
我們模擬瀏覽器原生的事件來實作自訂事件(en:自訂事件名稱,fn:事件處理函數,addEvent:為DOM元素添加自訂事件,triggerEvent:觸發自訂事件):
window.onload = function(){ var demo = document.getElementById("demo"); demo.addEvent("test",function(){console.log("handler1")}); demo.addEvent("test",function(){console.log("handler2")}); demo.onclick = function(){ this.triggerEvent("test"); } } Element.prototype.addEvent = function(en,fn){ this.pools = this.pools || {}; if(en in this.pools){ this.pools[en].push(fn); }else{ this.pools[en] = []; this.pools[en].push(fn); } } Element.prototype.triggerEvent = function(en){ if(en in this.pools){ var fns = this.pools[en]; for(var i=0,il=fns.length;i<il;i++){ fns[i](); } }else{ return; } }
由我們自己執行的函數是函數調用,非我們執行的函數我們可以叫做觸發事件,既然函數不是由我們呼叫的,那麼呼叫者怎麼知道要呼叫哪些函數就是一個問題了,所以就需要在加入事件函數和觸發事件函數之間加上一些約束了,那就是兩者之間有一個都能存取的事件池,新增事件時把事件及對應的處理函數放在這個池子裡,當滿足觸發條件時就去池子裡找到要觸發的事件,執行對應的處理函數,所以就有了我們上面的那一段程式碼。
對同一個功能(事件)可能有很多個處理函數,所以我們就需要一個集合去儲存這些處理函數,這時我們應該反映出兩個方案JSON或數組,JSON的結構是key :value,對於處理函數來說名字是沒有什麼作用的所以我們用數組來保存處理函數,這組函數是處理什麼功能的,所以我們還需要對這組處理函數由一個說明這時候就需要JSON了-->{eventName:[]}。
以簡化的BootStrap模態視窗來示範自訂事件的作用:
window.onload = function(){ var show = document.getElementById("show"); var hide = document.getElementById("hide"); var content = document.getElementById("content"); show.onclick = function(){ content.modal("show"); } hide.onclick = function(){ content.modal("hide"); } content.addEvent("show",function(){alert("show before")}); content.addEvent("shown",function(){ document.getElementById("input").focus(); alert("show after"); }); } ;(function(ep){ ep.addEvent = function(en,fn){ this.pools = this.pools || {}; if(en in this.pools){ this.pools[en].push(fn); }else{ this.pools[en] = []; this.pools[en].push(fn); } } ep.triggerEvent = function(en){ if(en in this.pools){ var fns = this.pools[en]; for(var i=0,il=fns.length;i<il;i++){ fns[i](); } }else{ return; } } ep.modal = function(t){ switch(t){ case "show": this.triggerEvent("show"); this.style.display = "block"; setTimeout(function(){this.triggerEvent("shown")}.bind(this),0);//该定时器主要是为了在视觉上先看见content,在弹出消息 break; case "hide": this.style.display = "none"; break; default: break; } } }(Element.prototype));
我們可以預先定義好在彈窗出現之前和出現之後的處理函數,當彈跳窗觸發對應事件的時候就執行對應的處理函數。
相關推薦:
以上是關於JavaScript自訂事件詳細分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!