JavaScript 自定義事件之我見(jiàn)
事件
技術(shù)一般水平有限,有什么錯(cuò)的地方,望大家指正。
事件就是用戶和瀏覽器交互的一種途徑。假如一個(gè)用戶注冊(cè)的功能,我們?cè)谔顚?xiě)完基本信息之后,點(diǎn)擊提交按鈕就可以實(shí)現(xiàn)注冊(cè)功能,要想完成這個(gè)功能所需要的就是點(diǎn)擊事件。我們預(yù)先定義好操作行為,在用戶點(diǎn)擊提交按鈕時(shí)就執(zhí)行我們預(yù)先定好的行為,在本例中我們的代碼邏輯一般就是收集用戶填寫(xiě)信息,驗(yàn)證信息合法性,利用AJAX與服務(wù)器交互。
這個(gè)過(guò)程就好像我們平時(shí)封裝函數(shù)然后調(diào)用函數(shù)一樣,事件其實(shí)也就類似函數(shù)定義函數(shù)調(diào)用這樣的一個(gè)過(guò)程,只不過(guò)事件函數(shù)的調(diào)用是由用戶的一些操作來(lái)告知瀏覽器,讓瀏覽器在去調(diào)用函數(shù)的。
首先瀏覽器已經(jīng)給我們提供了一列的事件,包括click,keydown等等,為什么還需要自定義事件呢?其實(shí)就是對(duì)我們的行為進(jìn)行更準(zhǔn)確的描述。以上面的用戶注冊(cè)為例我們可以定義一個(gè)名為saveMessage的事件,在點(diǎn)擊提交按鈕時(shí)觸發(fā)這個(gè)事件,好像看起來(lái)更加直觀一些,不過(guò)這看起來(lái)和普通的函數(shù)調(diào)用沒(méi)什么區(qū)別,仔細(xì)想了想函數(shù)調(diào)用和事件觸發(fā)的區(qū)別就是由我們自己執(zhí)行的函數(shù)就是函數(shù)調(diào)用,不是由我們執(zhí)行的函數(shù)就是事件觸發(fā)。看下面的代碼:
window.onload = function(){ var demo = document.getElementById("demo"); demo.onclick = handler; function handler(){ console.log("aaa"); } }
在我們點(diǎn)擊按鈕的時(shí)候就會(huì)打印aaa,而且很明顯的可以看出函數(shù)并不是由我們調(diào)用的而是由瀏覽器來(lái)執(zhí)行的,如果我們直接調(diào)用函數(shù)handler()一樣可以打印aaa但這是由我們調(diào)用的所以是函數(shù)調(diào)用。
自定義事件的作用
自定義事件就是我們按照瀏覽器對(duì)事件的機(jī)制來(lái)自定義的函數(shù)。自定義事件,可以對(duì)我們的處理函數(shù)帶來(lái)更好的說(shuō)明,也可以為我們的插件帶來(lái)更好的處理流程。假如我們又一個(gè)這樣的需求:從服務(wù)器端拉取一組數(shù)據(jù)然后在HTML中顯示成列表,然后標(biāo)識(shí)出第一條數(shù)據(jù),假如我們利用一個(gè)現(xiàn)有的處理函數(shù),我們可能會(huì)這樣來(lái)寫(xiě):
dataTable("url"); $("table").find("input[type='checkbox']:first").prop("checked",true);
這是不能達(dá)到我們目的的因?yàn)镴S是單線程的而AJAX是異步的,當(dāng)代碼$("table").find("input[type='checkbox']:first").prop("checked",true)執(zhí)行的時(shí)候,我們需要的數(shù)據(jù)還沒(méi)有獲取到。我們?nèi)バ薷牟寮膬?nèi)部實(shí)現(xiàn)顯然是不明智的,一個(gè)可以被人接受的插件必然是有合理的回調(diào)函數(shù)(或者自定義事件)的,假如現(xiàn)在有一個(gè)列表繪制成功的回調(diào)函數(shù),我們就可以把這個(gè)回調(diào)函數(shù)看做是一個(gè)事件,我們可以對(duì)這個(gè)事件添加事件操作,定義好處理函數(shù),然后在列表繪制成功時(shí)讓插件來(lái)執(zhí)行這個(gè)處理函數(shù)。
自定義事件實(shí)現(xiàn)
我們模擬瀏覽器原生的事件來(lái)實(shí)現(xiàn)自定義事件(en:自定義事件名稱,fn:事件處理函數(shù),addEvent:為DOM元素添加自定義事件,triggerEvent:觸發(fā)自定義事件):
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; } }
由我們自己執(zhí)行的函數(shù)是函數(shù)調(diào)用,非我們執(zhí)行的函數(shù)我們可以叫做觸發(fā)事件,既然函數(shù)不是由我們調(diào)用的,那么調(diào)用者怎樣知道調(diào)用哪些函數(shù)就是一個(gè)問(wèn)題了,所以就需要在添加事件函數(shù)和觸發(fā)事件函數(shù)之間加上一些約束了,那就是兩者之間有一個(gè)都能訪問(wèn)到的事件池,添加事件時(shí)把事件及對(duì)應(yīng)的處理函數(shù)放在這個(gè)池子里,當(dāng)滿足觸發(fā)條件時(shí)就去池子里找到要觸發(fā)的事件,執(zhí)行對(duì)應(yīng)的處理函數(shù),所以就有了我們上面的那一段代碼。
對(duì)同一個(gè)功能(事件)可能有很多個(gè)處理函數(shù),所以我們就需要一個(gè)集合去存儲(chǔ)這些處理函數(shù),這時(shí)我們應(yīng)該反映出兩個(gè)方案JSON或者數(shù)組,JSON的結(jié)構(gòu)是key:value,對(duì)于處理函數(shù)來(lái)說(shuō)名字是沒(méi)有什么作用的所以我們用數(shù)組來(lái)保存處理函數(shù),這組函數(shù)是處理什么功能的,所以我們還需要對(duì)這組處理函數(shù)由一個(gè)說(shuō)明這時(shí)候就需要JSON了-->{eventName:[]}。
以簡(jiǎn)化的BootStrap模態(tài)窗來(lái)演示自定義事件的作用:
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);//該定時(shí)器主要是為了在視覺(jué)上先看見(jiàn)content,在彈出消息 break; case "hide": this.style.display = "none"; break; default: break; } } }(Element.prototype));
我們可以預(yù)先定義好在彈窗出現(xiàn)之前和出現(xiàn)之后的處理函數(shù),當(dāng)彈窗觸發(fā)對(duì)應(yīng)事件的時(shí)候就執(zhí)行對(duì)應(yīng)的處理函數(shù)。
- Javascript自定義事件詳解
- js事件模型與自定義事件實(shí)例解析
- 詳解JavaScript中的自定義事件編寫(xiě)
- nodejs 中模擬實(shí)現(xiàn) emmiter 自定義事件
- 詳解javascript實(shí)現(xiàn)自定義事件
- JavaScript中自定義事件用法分析
- Nodejs中自定義事件實(shí)例
- JavaScript自定義事件介紹
- js實(shí)現(xiàn)屏蔽默認(rèn)快捷鍵調(diào)用自定義事件示例
- js自定義事件及事件交互原理概述(二)
- js自定義事件及事件交互原理概述(一)
- js自定義事件代碼說(shuō)明
- javascript 自定義事件初探
相關(guān)文章
JS幾個(gè)常用的函數(shù)和對(duì)象定義與用法示例
這篇文章主要介紹了JS幾個(gè)常用的函數(shù)和對(duì)象定義與用法,涉及JavaScript日期時(shí)間、數(shù)值計(jì)算及變量判斷等相關(guān)操作技巧,需要的朋友可以參考下2020-01-01JavaScript取得鍵盤(pán)按下方向鍵是哪個(gè)的方法
這篇文章主要介紹了JavaScript取得鍵盤(pán)按下方向鍵是哪個(gè)的方法,涉及javascript針對(duì)鍵盤(pán)按鍵事件的判定技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08原型方法的不同寫(xiě)法居然會(huì)影響調(diào)試的解決方法
原型方法的不同寫(xiě)法居然會(huì)影響調(diào)試的解決方法...2007-03-03three.js實(shí)現(xiàn)3D影院的原理的代碼分析
本篇文章主要給大家講解了如何通過(guò)three.js實(shí)現(xiàn)3D影院的功能以及原理分析,需要的朋友參考一下吧。2017-12-12在JavaScript中構(gòu)建ArrayList示例代碼
這篇文章主要介紹了在JavaScript中構(gòu)建ArrayList,很實(shí)用,需要的朋友可以參考下2014-09-09JavaScript實(shí)現(xiàn)圖像壓縮的方法
使用 JavaScript 和 canvas 壓縮圖像可以使用 canvas 的 drawImage() 方法將圖像繪制到 canvas 上,然后使用 toDataURL() 方法將圖像轉(zhuǎn)換為 Data URL 形式,這篇文章主要介紹了JavaScript 圖像壓縮的相關(guān)資料,需要的朋友可以參考下2023-01-01