欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript 自定義事件之我見(jiàn)

 更新時(shí)間:2017年09月25日 17:23:12   作者:小前端  
事件就是用戶和瀏覽器交互的一種途徑,在本例中我們的代碼邏輯一般就是收集用戶填寫(xiě)信息,驗(yàn)證信息合法性,利用AJAX與服務(wù)器交互,需要的朋友可以參考下

事件

  技術(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ù)。

相關(guān)文章

最新評(píng)論