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

JavaScript 自定義事件之我見

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

事件

  技術(shù)一般水平有限,有什么錯的地方,望大家指正。

  事件就是用戶和瀏覽器交互的一種途徑。假如一個用戶注冊的功能,我們在填寫完基本信息之后,點(diǎn)擊提交按鈕就可以實(shí)現(xiàn)注冊功能,要想完成這個功能所需要的就是點(diǎn)擊事件。我們預(yù)先定義好操作行為,在用戶點(diǎn)擊提交按鈕時就執(zhí)行我們預(yù)先定好的行為,在本例中我們的代碼邏輯一般就是收集用戶填寫信息,驗(yàn)證信息合法性,利用AJAX與服務(wù)器交互。

  這個過程就好像我們平時封裝函數(shù)然后調(diào)用函數(shù)一樣,事件其實(shí)也就類似函數(shù)定義函數(shù)調(diào)用這樣的一個過程,只不過事件函數(shù)的調(diào)用是由用戶的一些操作來告知瀏覽器,讓瀏覽器在去調(diào)用函數(shù)的。

  首先瀏覽器已經(jīng)給我們提供了一列的事件,包括click,keydown等等,為什么還需要自定義事件呢?其實(shí)就是對我們的行為進(jìn)行更準(zhǔn)確的描述。以上面的用戶注冊為例我們可以定義一個名為saveMessage的事件,在點(diǎn)擊提交按鈕時觸發(fā)這個事件,好像看起來更加直觀一些,不過這看起來和普通的函數(shù)調(diào)用沒什么區(qū)別,仔細(xì)想了想函數(shù)調(diào)用和事件觸發(fā)的區(qū)別就是由我們自己執(zhí)行的函數(shù)就是函數(shù)調(diào)用,不是由我們執(zhí)行的函數(shù)就是事件觸發(fā)??聪旅娴拇a:

window.onload = function(){
 var demo = document.getElementById("demo");
 demo.onclick = handler;
 function handler(){
  console.log("aaa");
 }
}

在我們點(diǎn)擊按鈕的時候就會打印aaa,而且很明顯的可以看出函數(shù)并不是由我們調(diào)用的而是由瀏覽器來執(zhí)行的,如果我們直接調(diào)用函數(shù)handler()一樣可以打印aaa但這是由我們調(diào)用的所以是函數(shù)調(diào)用。

自定義事件的作用

  自定義事件就是我們按照瀏覽器對事件的機(jī)制來自定義的函數(shù)。自定義事件,可以對我們的處理函數(shù)帶來更好的說明,也可以為我們的插件帶來更好的處理流程。假如我們又一個這樣的需求:從服務(wù)器端拉取一組數(shù)據(jù)然后在HTML中顯示成列表,然后標(biāo)識出第一條數(shù)據(jù),假如我們利用一個現(xiàn)有的處理函數(shù),我們可能會這樣來寫:

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ù)據(jù)還沒有獲取到。我們?nèi)バ薷牟寮膬?nèi)部實(shí)現(xiàn)顯然是不明智的,一個可以被人接受的插件必然是有合理的回調(diào)函數(shù)(或者自定義事件)的,假如現(xiàn)在有一個列表繪制成功的回調(diào)函數(shù),我們就可以把這個回調(diào)函數(shù)看做是一個事件,我們可以對這個事件添加事件操作,定義好處理函數(shù),然后在列表繪制成功時讓插件來執(zhí)行這個處理函數(shù)。

自定義事件實(shí)現(xiàn)

  我們模擬瀏覽器原生的事件來實(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ù)就是一個問題了,所以就需要在添加事件函數(shù)和觸發(fā)事件函數(shù)之間加上一些約束了,那就是兩者之間有一個都能訪問到的事件池,添加事件時把事件及對應(yīng)的處理函數(shù)放在這個池子里,當(dāng)滿足觸發(fā)條件時就去池子里找到要觸發(fā)的事件,執(zhí)行對應(yīng)的處理函數(shù),所以就有了我們上面的那一段代碼。

  對同一個功能(事件)可能有很多個處理函數(shù),所以我們就需要一個集合去存儲這些處理函數(shù),這時我們應(yīng)該反映出兩個方案JSON或者數(shù)組,JSON的結(jié)構(gòu)是key:value,對于處理函數(shù)來說名字是沒有什么作用的所以我們用數(shù)組來保存處理函數(shù),這組函數(shù)是處理什么功能的,所以我們還需要對這組處理函數(shù)由一個說明這時候就需要JSON了-->{eventName:[]}。

  以簡化的BootStrap模態(tà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);//該定時器主要是為了在視覺上先看見content,在彈出消息
    break;
   case "hide":
    this.style.display = "none";
    break;
   default:
    break;
  }
 }

}(Element.prototype));

我們可以預(yù)先定義好在彈窗出現(xiàn)之前和出現(xiàn)之后的處理函數(shù),當(dāng)彈窗觸發(fā)對應(yīng)事件的時候就執(zhí)行對應(yīng)的處理函數(shù)。

相關(guān)文章

最新評論