事件處理程序

簡介

js和html之間的交互是經過事件實現的,所謂事件就是文檔或瀏覽器窗口中發生的一些特定的交互瞬間。對於事件的處理,瀏覽器存在差別,主要是IE的兼容性問題,因此大部分都是兼容的,封裝成一個事件庫,方便調用。css


一、事件流

事件流描述的是從頁面接收事件的順序,分爲事件冒泡流和事件捕獲流html

事件冒泡:IE瀏覽器的事件流,開始由最具體的元素接收,而後逐級向上傳播到不那麼具體的節點上程序員

事件捕獲:Netscape提出的,開始由不那麼具體的節點,而後逐級向下傳播到最具體的元素接收;在事件到達以前捕獲它(老瀏覽器不支持,建議用事件冒泡)web

DOM事件流:DOM2規定事件流包括事件捕獲,處於目標階段和事件冒泡瀏覽器

二、事件處理程序

響應某個事件的函數就是事件處理程序緩存

2.1HTML事件處理程序app

<div class="div" title="div box" onclick="changeColor()" onmouseover="alert(this.title)"></div>
function changeColor(){
alert("變顏色")
}
這種就爲html事件處理程序
優勢:拓展做用域,能夠無需引用元素就能夠訪問元素屬性
缺點:時差問題,事件函數不一致,通常onclick="try{showMessage()}catch(ex){}";html和js過於耦合,通常不採起
給相應的屬性值設置爲null,也能夠刪除了事件處理程序

2.2DOM0級事件處理程序ide

<div id="div" title="div box"></div>
div=document.getELementById("div")
div.onclick=function(){
alert("DOM0級事件處理程序")
alert(this.title) 事件處理程序就是在元素的做用域下進行的,能夠用this
}
div.onclick=null 刪除事件處理程序(通用)

2.3DOM2級事件處理程序函數

DOM定義事件處理程序有兩種方法:性能

addEventListener(),removeEventListener(),接受三個參數,處理的事件名、事件函數、布爾值(true爲捕獲,false爲冒泡,默認爲false)

var div=document.getElementById("div")
div.addEventListener("click",function(){alert("DOM2級事件處理程序")},false)
div.addEventListener("click",function(){alert("能夠添加幾個事件處理程序,順序執行")},false)
當removeEventListener時候,中間事件函數必須爲函數表達式,不能爲匿名函數
div.addEventListener("click",handler,false)
var handler=function(){
alert("函數表達式形式")
}
div.removeEventListener("click",handler,false) 這裏能夠刪除事件處理程序

補充

 addEventListener的第三個參數

1 默認爲false即冒泡事件,在都不添加的狀況下爲冒泡

2 一旦有設置爲true的,則true先觸發

3 在沒有子節點的時候,即單一觸發,則誰先誰觸發

<label>Click me <input type="text"></label>
<script>
    document.querySelector('label').addEventListener('click',function () {
        console.log(1)
    })
    document.querySelector('input').addEventListener('click',function () {
        console.log(2)
    })
</script>

瞭解label和input間的綁定關係便可知道,每點擊label的時候,也會點擊input,那麼在這種狀況下,會彈出1 2 1    第一則爲label本身,而2 1 則是冒泡事件 

2.4IE事件處理程序

與DOM2級類似爲attachEvent()和detachEven(),接受兩個參數,處理事件名(這裏是帶on的),事件函數

var div=document.getELementById("div")
div.attachEvent("onclick",function(){alert("IE瀏覽器")}) 這裏的和DOM0級的區別在於做用域,DOM0級爲該元素內,而IE爲整個window,this爲window,後面的event對象爲window.event
div.attachEvent("onclick",function(){alert("多個事件則以相反順序執行")})
detachEvent和DOM2級同樣的

2.5跨瀏覽器兼容

var EventUtil={
//添加事件處理程序 addHandler:
function(element,type,handler){ //handler爲函數,須要函數表達式,不會函數提高的 if(element.addEventListener){ element.addEventListener(type,handler,false); } else if(element.attachEvent){ element.attachEvent("on"+type,handler); } else{ element["on"+type]=handler; } }, //刪除事件處理程序 removeHandler:function(element,type,handler){ if(element.removeEventListener){ element.removeEventListener(type,handler,false) } else if(element.detachEvent){ element.detachEvent("on"+type,handler) } else{ element["on"+type]=null } } }

三、事件對象

當觸發DOM事件時,就會產生一個事件對象event,包含着全部與事件有關的信息,包括致使事件的元素、事件的類型、以及其餘與特定事件相關的信息,瀏覽器支持event,但方式不一,event對象常見的屬性和方法

DOM中

type爲事件類型

target爲事件目標

currentTarget正在處理事件的元素,即誰在處理事件程序就是誰,爲this,而target則是老是在實際觸發事件的元素上的。

preventDefault()取消事件默認行爲,好比a標籤自己的跳轉

stopPropagation()取消事件的進一步捕獲或冒泡

IE中

type爲事件類型

srcElement爲事件目標

returnValue設置爲false取消事件默認行爲

cancelBubble設置爲true取消事件冒泡

直接上兼容版的

var EventUtil={              
             //兼容event對象(關鍵)
             getEvent:function(event){
                  return event?event:window.event;
             },
             //得到目標
             getTarget:function(event){
                  return event.target||event.srcElement;
             },
             //取消默認行爲
             previousDefault:function(event){
                 if(event.previousDefault){
                     event.previousDefault();
                 }
                 else{
                     event.returnValue=false;
                 }
             },
             //取消事件冒泡
             stopPropagation:function(event){
                  if(event.stopPropagation){
                      event.stopPropagation();
                  }
                  else{
                      event.cancelBubble=true;
                  }
             },
       }

 4事件類型

4.1UI事件

load事件

當頁面徹底加載後在window觸發;當img加載後在img上觸發;通常用js指定事件處理程序,固然在html內body也能夠的,

EventUtil.addHandler(window,"load",function(){
                   var  image=document.createElement("img")
                   document.body.appendChild(image)
                   image.src="console.png"
                   EventUtil.addHandler(image,"load",function(event){
                            event=EventUtil.getEvent(event)
                            alert(EventUtil.getTarget(event).src)          //在圖像徹底加載後得到信息
                   })
          })

unload事件

當頁面徹底卸載後觸發,從一個頁面跳轉到另外一個頁面就會觸發unload事件,通常利用其清楚引用,以避免避免內存泄露。

resize事件

當改變窗口大小就會觸發,以1px爲單位

scroll事件

當頁面滾動時發生,單位因各個瀏覽器不一樣,scrollTop和scrollLeft的兼容性問題

4.2焦點事件

焦點事件會在頁面元素得到失去焦點時觸發,與document.hasFocus(),document.activeElement屬性配合,知道用戶在頁面的行蹤

blur失去焦點時觸發,不會冒泡

focus得到焦點時觸發,不會冒泡

focusout失去焦點時觸發,會冒泡

focusin得到焦點時觸發,會冒泡

4.3鼠標事件

客戶區座標位置

EventUtil.addHandler(window,"load",function(event){
                   EventUtil.addHandler(window,"click",function(event){
                            event=EventUtil.getEvent(event)
                            alert(event.clientX+","+event.clientY)
                   })
          })
老是相對於整個可視區範圍的

頁面座標位置

EventUtil.addHandler(window,"click",function(event){
                    event=EventUtil.getEvent(event)
                    console.log(event.pageX+","+event.pageY)
          })
兩個效果同樣的,page事實上爲scrollTop和clientY的和,下面這種兼容性能夠的
EventUtil.addHandler(window,"click",function(event){
                   var event=EventUtil.getEvent(event)
                   var scrollTop=Math.ceil(document.documentElement.scrollTop||document.body.scrollTop)
                   alert(event.clientX+","+(event.clientY+scrollTop))
          })

修改鍵

鍵盤上的某些鍵也能夠達到鼠標鍵的效果,DOM中常見的有shiftKey,ctryKey,altKey,metaKey(window or cmd),都是布爾值。

EventUtil.addHandler(another,"click",function(event){
                 event=EventUtil.getEvent(event)
                 var key=[]
                 if(event.ctrlKey){
                      key.push("ctrlKey")
                 }
                 if(event.shiftKey){
                      key.push("shiftKey")
                 }
                 if(event.altKey){
                      key.push("altKey")
                 }
                 if(event.metaKey){
                     key.push("metaKey")
                 }
                console.log(key.join(","))
       })

屏幕座標位置

EventUtil.addHandler(window,"click",function(event){
                    event=EventUtil.getEvent(event)
                    console.log(event.screenX+","+event.screenY)
          })

相關元素

通常對於mouseover和mouseout,其餘的事件爲null,當從原來的元素轉移到另外一元素,另外一元素即爲相關元素

getRelatedTarget:function(event){
                 if(event.relatedTarget){
                      return event.relatedTarget;
                 }
                  else if(event.toElement){       兼容IE8版本
                       return event.toElement
                  }
                  else if(event.formElement){
                       return event.formElement
                  }
                else{
                    return null
                }
             },

鼠標按鈕

 getButton:function(event){
                   if(document.implementation.hasFeature("MouseEvent","2.0")){
                          return event.button
                   }
                   else{
                        switch(event.button){
                             case 0:
                             case 1:
                             case 3:
                             case 5:
                             case 7:
                                return 0;
                             case 2:
                             case 6:
                                return 2;
                             case 4:
                                return 1;
                        }
                   }
             },

鼠標滾輪事件

觸發mousewheel事件(火狐爲DOMMouseScroll),event對象屬性wheelDelta,能夠獲得滾輪的增量值,IE爲正負120,Chrome爲正負150,火狐爲正負120

             //鼠標滾輪事件mousewheel
             getWheelDelta:function(event){
                  if(event.wheelDelta){
                       return (client.engine.opear&&client.engine.opear<9.5?-event.wheelDelta:event.wheelDelta);
                  }
                  else{
                       return -event.detail*40;
                  }
             },

var client=function(){     //聲明瀏覽器引擎問題
                 var engine={
                      //呈現引擎
                      ie:0,
                      gecko:0,
                      webkit:0,
                      khtml:0,
                      opera:0,
                      //具體版本號
                      ver:null
                 };
                 return{
                       engine:engine
                 };
          }();

(function(){ //這裏的函數是個私有做用域,不會讓其干預到全局做用域 function handlerMouseWheel(event){ event=EventUtil.getEvent(event); var delta=EventUtil.getWheelDelta(event) console.log(delta); } EventUtil.addHandler(window,"mousewheel",handlerMouseWheel); //其餘瀏覽器 EventUtil.addHandler(window,"DOMMouseScroll",handlerMouseWheel); //火狐瀏覽器 })()

4.4鍵盤和文本事件

鍵盤事件主要有三個keydown任意鍵,keypress字符鍵,keyup釋放鍵,這三個在輸入文本時經常使用;文本事件爲textInput,在文本輸入文本框中才觸發。

鍵碼:發生鍵盤事件時,event對象中keyCode屬性進行判斷,keyCode屬性值和ASCII相對應,

經常使用的keyCode爲

空格鍵32 tab鍵9 enter鍵13  shift鍵16  Ctrl鍵17 alt鍵18 backspace鍵8 方向鍵37,38,39,40

字符編碼:按下可以插入或刪除字符的鍵才觸發charCode屬性,只有發生keypress時才包含,表示其的ASCII編碼,

              //字符編碼
             getCharCode:function(event){
                 if(typeof event.charCode=="number"){
                      return event.charCode;
                 }
                 else{
                      return event.keyCode; 
                 }
             },

            EventUtil.addHandler(text1,"keypress",function(event){
                 event=EventUtil.getEvent(event)
               console.log(EventUtil.getCharCode(event))
            })

 4.5HTML5事件

contextmenu事件

單擊右鍵觸發上下文事件,將原來的默認事件取消,contextmenu事件是冒泡的,因此用能夠用document處理頁面全部此類事件

#move{
   width:200px;
   height:400px;
   background:pink;
   position:absolute;
   display:none;
}

  var move=document.getElementById("move")
EventUtil.addHandler(document,"contextmenu",function(event){ event=EventUtil.getEvent(event) EventUtil.previousDefault(event) move.style.left=event.clientX+"px" move.style.top=event.clientY+"px" move.style.display="block" EventUtil.addHandler(document,"click",function(event){ move.style.display="none" }) })

beforeunload事件

當頁面卸載前阻止這一操做(好比刷新),將控制權交給用戶,是否卸載此頁面,提醒做用

    EventUtil.addHandler(window,"beforeunload",function(event){
                     event=EventUtil.getEvent(event)
                     EventUtil.previousDefault(event)
                     var message="really to leave"                   
          })

DOMContentLoaded事件

此事件在load事件以前發生,不會由於加載外部的css或者js等文件資源而延遲,使得用戶更早的交互,對於不支持此事件好比IE8,9等,能夠採用定時器的方法

          setTimeout(function(){alert("breforeload"),0})  對於不支持的採起這種,可是也不能夠保證
EventUtil.addHandler(window,
"load",function(){ alert("load") }) EventUtil.addHandler(document,"DOMContentLoaded",function(event){ alert("beforeload") })

readystatechange事件:提供與文檔或元素加載情況的信息

pageshow和pagehide事件

往返緩存(bfcache),能夠在用戶使用瀏覽器後退或前進按鈕加載頁面的轉換速度,不只保存頁面數據,還保存DOM,js狀態,將整個頁面保存在內存中。

pageshow事件。在頁面顯示時觸發,不管是否來自bfcache,雖然是在document觸發的,可是必須在window上進行事件程序員處理

function change(){
                  var count=0

                  EventUtil.addHandler(window,"load",function(){
                       alert("load")
                  })

                  EventUtil.addHandler(window,"pageshow",function(event){
                         count++
                         alert(event.persisted)   //判斷頁面是否保存在往返緩存中,布爾值
                  })

                  EventUtil.addHandler(window,"pagehide",function(event){
                         alert(event.persisted)   //當卸載頁面時觸發
                  })
          }
 change()

hashchange事件

在URL的參數列表發生變化時通知,在Ajax應用中,利用URL參數列表保存狀態或導航信息;此時Event有oldURL和newURL屬性分別保存先後完整的參數列表的URL,不過兼容瀏覽器直接用location判斷。

EventUtil.addHandler(window,"hashchange",function(event){
                      alert(locationn.hash)     //使用location對象肯定當前的參數列表
          })

4.6設備事件暫時不考慮,等涉及到移動端再好好補充

5內存和性能

5.1事件委託

所謂事件委託就是利用事件冒泡,只給指定一個事件處理程序,就能夠管理某一類型的全部事件,解決的就是事件處理程序太多的問題,以此提升性能;適合採用這種方法的有click,mousedown,keydown,keyup,keypress

EventUtil.addHandler(list,"click",function(event){      只須要在一個ul上添加事件,而後經過target來實現行爲,這也就是target和currentTarget之間的區別,好處多多
                    event=EventUtil.getEvent(event)
                    var target=EventUtil.getTarget(event)

                    switch(target.id){                //利用條件判斷
                           case "baidu":
                                target.style.color="red"
                                target.style.cursor="pointer"
                                document.title="i have change"
                                break;
                           case "ali":
                                location.href="http://www.baidu.com"
                                break;
                           case "tengxun":
                                alert("Tencent")
                                break;
                    }
          })

5.2移除事件程序

當不須要事件時,須要將已有的事件處理程序移除即那些過期不用的空事件處理程序(dangling event handler),好比innerHTML代替原來的東西,原來的事件必須移除以此提升性能。當已知的元素即將移除,最好手工移除事件好比下面。

var btn=document.getElementById("btn")
          btn.onclick=function(){
                  alert("事件發生後,我就再也不須要了")
                  btn.onclick=null
          }

模擬事件暫時不須要,之後再細細道來

基礎不牢,地動山搖

相關文章
相關標籤/搜索