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.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.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 }
模擬事件暫時不須要,之後再細細道來