js和HTML之間交互是通過事件實(shí)現(xiàn)的屯曹。事件會(huì)有事件流。事件描述的是從頁面接受事件的順序。IE和網(wǎng)景提出了差不多相反的事件流概念恶耽。IE提出事件冒泡流密任。網(wǎng)景提出事件捕獲流。
事件冒泡:事件開始時(shí)由最具體的元素接收偷俭,然后逐級(jí)向上傳播到較不具體的節(jié)點(diǎn)浪讳。所有現(xiàn)代瀏覽器幾乎都支持冒泡。
事件捕獲:不具體的節(jié)點(diǎn)更早的接收事件社搅,最具提的節(jié)點(diǎn)最后接收到事件驻债。IE9以上可以支持捕獲。
DOM2級(jí)規(guī)定的事件流包括三個(gè)階段(IE8及更早版本不支持事件流):
- 事件捕獲階段
- 處于目標(biāo)階段
- 事件冒泡階段形葬。
事件處理程序:
- HTML事件處理程序
- DOM0級(jí)事件處理程序
- DOM2級(jí)事件處理程序
HTML事件處理程序
<input type='button' id='btn' onclick=clickMe() value='click me'>
function clickMe (){
alert('hi')
} //這種處理程序代碼耦合度太高,修改時(shí)需要修改兩處暮的。存在時(shí)差問題笙以,有些事件可能需要HTML元素一出現(xiàn)在頁面上就觸發(fā),但當(dāng)時(shí)的事件處理程序可能尚不具備條件冻辩。
DOM0級(jí)事件處理程序:
var btn =document.getElementById('btn')
btn.onclick = function () {//每個(gè)事件只支持一個(gè)事件處理程序
alert('hi')
}
btn.onclick = null //刪除事件處理程序
DOM2級(jí)事件處理程序:IE9及以上支持
使用DOM2級(jí)事件處理程序的好處是可以為一個(gè)元素綁定多個(gè)事件處理程序
var btn =document.getElementById('btn')
btn.addEventListener('click',function(){
alert('hi')
},false) //click事件在冒泡階段觸發(fā)
IE事件處理程序:IE8及以下只支持事件冒泡
var btn =document.getElementById('btn')
btn.attachEvent('onclick',funtion(){ //第一個(gè)參數(shù)為onclick猖腕,并不是click。
alert('hi') //attachEvent()添加的事件處理程序都會(huì)被添加到冒泡階段
})
在IE中使用attachEvent()與使用DOM0級(jí)方法的主要區(qū)別:事件處理程序運(yùn)行的作用域不一樣恨闪。DOM0級(jí)事件處理程序會(huì)在其所屬元素的作用域下運(yùn)行倘感,而attachEvent()的事件處理程序會(huì)在全局作用域運(yùn)行。attachEvent()也可以為一個(gè)元素添加多個(gè)事件處理程序咙咽,執(zhí)行順序與DOM2級(jí)事件處理程序的執(zhí)行順序相反老玛。
跨瀏覽器事件處理程序
var EventUtil = {
addEvent:function (element,type,handler) {
if (element.addEventListener) { //ie9及以上
element.addEventListener(type,handler, false)
} else if (element.attachEvent) { //ie8及以下
element.attachEvent('on'+type,handler)
} else {
element['on'+type] = handler
}
},
removeEvent:function(element, type,handler) {
if (element.removeEventListener) {//ie9及以上
element.removeEventListener(type,handler, false)
} else if (element.detachEvent) { //ie8及以下
element.detachEvent('on'+type,handler)
} else {
element['on'+type] = null
}
}
}
<input type='button' id='btn' value='click me'>
var btn =document.getElementById('btn')
var handler = function () {
alert('hi')
}
EventUtil.addEvent(btn,'click',handler)
EventUtil.removeEvent(btn,'click',handler)
事件對(duì)象
在觸發(fā)DOM上的某個(gè)事件時(shí),會(huì)產(chǎn)生事件對(duì)象event钧敞。這個(gè)對(duì)象包含與這個(gè)事件有關(guān)的信息蜡豹。
DOM中的事件對(duì)象
兼容DOM的瀏覽器會(huì)將一個(gè)event對(duì)象傳入到事件處理程序中,無論是DOM0級(jí)還是DOM2級(jí)溉苛。
var btn = document.getElementByid('btn')
btn.onclick = function (event) {
alert(event.type) //click
}
btn.addEventListener('click',function (event) {
alert(event.type) //click
}, false)
- cancelable 表示是否可以取消事件的默認(rèn)行為
- preventDefault() 阻止默認(rèn)操作 cancelable屬性需要設(shè)置為true
- bubbles 表示事件是否冒泡
- stopPropagation() 取消事件的捕獲或冒泡镜廉。如果bubbles為true
- event.target 時(shí)間的目標(biāo)
- event.type 事件類型
- event.currentTarget 正在處理事件的元素
- event.eventPhase 確定事件當(dāng)前正處于事件流的那個(gè)階段 1表示捕獲階段 2 處于目標(biāo)對(duì)象上 3 冒泡階段
只有在事件處理程序執(zhí)行期間,event對(duì)象才會(huì)存在愚战,一旦事件處理程序執(zhí)行完成娇唯,event對(duì)象就會(huì)被銷毀
IE中的事件對(duì)象
要訪問IE中的event對(duì)象有幾種不同的方式,取決于事件處理程序的方法寂玲。DOM0級(jí)事件處理程序塔插,event對(duì)象作為window屬性存在。
使用attachEvent()的情況下敢茁,可以使用event對(duì)象佑淀,也可以通過window 對(duì)象來訪問event對(duì)象
- cancelBubble 默認(rèn)值是false,設(shè)置為true可以取消冒泡 與stoppropagation()作用相同
- returnValue 默認(rèn)是false,設(shè)置為true表示取消事件默認(rèn)行為 與* preventDefault()作用相同
- srcElement 事件的目標(biāo) 與target屬性相同
- type 事件類型
btn.onclick = function () {
alert (window.event.srcElement === this) //true
}
btn.attachEvent('onclick', function (event) {
alert(event.srcElement === this) //false
})
跨瀏覽器事件對(duì)象
var EventUtil = {
addEvent:function (element,type,handler) {
if (element.addEventListener) {
element.addEventListener(type,handler, false)
} else if (element.attachEvent) {
element.attachEvent('on'+type,handler)
} else {
element['on'+type] = handler
}
},
removeEvent: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
}
},
getEvent: function (event) {
return event ? event : window.event
} ,
getTarget: function (event) {
return event.target || event.srcElement
},
preventDefault: function (event) {
if (event.preventDefault) {
event.preventDefault ()
} else {
event.returnValue = false
}
},
stopPropagation: function (event) {
if (event.stopPropagation) {
event.stopPropagation ()
} else {
event.cancelBubble = true
}
}
}
btn.onclick = function (event) {
event = EventUtil.getEvent (event)
var target = EventUtil.getTarget (event)
EventUtil.preventDefault()
EventUtil.stopPropagation()
}
事件類型
UI事件(用戶與頁面上的元素交互時(shí)觸發(fā))/ 焦點(diǎn)事件 /鼠標(biāo)事件 /滾動(dòng)事件/鍵盤事件/文本事件/變動(dòng)事件/合成事件
UI事件指的是那些不一定與用戶操作有關(guān)的事件伸刃。
- load事件 頁面完全加載后window上觸發(fā)
- unload事件 頁面完全卸載后window上觸發(fā)谎砾,只要用戶從一個(gè)頁面切換到另一個(gè)頁面就會(huì)觸發(fā)
- abort事件 用戶停止下載過程時(shí),如果嵌入的內(nèi)容沒有加載完<object>上觸發(fā)
- error事件 當(dāng)js發(fā)生錯(cuò)誤時(shí)觸發(fā) 當(dāng)無法加載圖片時(shí)在img上觸發(fā) 當(dāng)無法加載嵌入的內(nèi)容時(shí)在<object>上觸發(fā)
- select事件 當(dāng)用戶選中文本框中的一個(gè)或多個(gè)字符時(shí)觸發(fā)
- resize事件 當(dāng)窗口或框架的大小變化時(shí)在window或框架上觸發(fā)
- scroll事件 當(dāng)用戶滾動(dòng)帶滾動(dòng)條的元素中的內(nèi)容時(shí)在該元素上觸發(fā)
- load事件中:圖片img可以實(shí)現(xiàn)預(yù)加載捧颅,新圖像元素不一樣要等到添加到文檔后才開始加載景图,只要設(shè)置了它的src屬性就會(huì)開始下載。而<script>標(biāo)簽也支持load事件碉哑,只不過只有設(shè)置了<script>標(biāo)簽的src屬性并且添加到文檔后挚币,才會(huì)開始下載js文件。
焦點(diǎn)事件
blur focus主要的兩個(gè)事件扣典,可以在捕獲階段偵聽到它們但是它們不支持冒泡妆毕。focusin和focusout與blur focus等價(jià),但是支持冒泡贮尖。
鼠標(biāo)事件
- click:用戶單擊主鼠標(biāo)或者按下回車鍵時(shí)觸發(fā)笛粘。
- dblclick:用戶雙擊主鼠標(biāo)時(shí)出大。屬于DOM3級(jí)事件標(biāo)準(zhǔn)
- mouseover:當(dāng)鼠標(biāo)指針位于一個(gè)元素外部湿硝,用戶將其首次移入另一個(gè)元素邊界訪問時(shí)觸發(fā)薪前,不能通過鍵盤觸發(fā)這個(gè)事件
- mouseout:當(dāng)鼠標(biāo)指針位于一個(gè)元素上方,然后用戶將其移入另一個(gè)元素時(shí)觸發(fā)关斜。不能通過鍵盤觸發(fā)這個(gè)事件
- mousedown:用戶按下任意鼠標(biāo)按鈕時(shí)觸發(fā)示括,不能通過鍵盤觸發(fā)這個(gè)事件
- mouseup:當(dāng)用戶釋放鼠標(biāo)按鈕時(shí)觸發(fā),不能通過鍵盤觸發(fā)這個(gè)事件
- mousemove:當(dāng)鼠標(biāo)在元素內(nèi)部移動(dòng)時(shí)重復(fù)觸發(fā)痢畜,不能通過鍵盤觸發(fā)這個(gè)事件
- mouseenter:在鼠標(biāo)光標(biāo)從外部首次移動(dòng)到元素范圍內(nèi)觸發(fā)垛膝,不支持冒泡,在光標(biāo)移動(dòng)到后代元素上不會(huì)觸發(fā)裁着。屬于DOM3級(jí)事件標(biāo)準(zhǔn)繁涂。
- mouseleave:在位于元素上方的鼠標(biāo)光標(biāo)移動(dòng)到元素范圍之外時(shí)觸發(fā),不支持冒泡二驰,在光標(biāo)移動(dòng)到后代元素上不會(huì)觸發(fā)扔罪。屬于DOM3級(jí)事件標(biāo)準(zhǔn)。
鼠標(biāo)事件都是在瀏覽器視口的特定位置上發(fā)生的桶雀。這個(gè)位置信息保存在事件對(duì)象的clientX矿酵,clientY屬性中。它們的值表示事件發(fā)生時(shí)鼠標(biāo)指針在視口的水平和垂直坐標(biāo)矗积。這些值不包含頁面滾動(dòng)的距離全肮,因此這個(gè)位置不表示鼠標(biāo)在頁面上的實(shí)際位置。
pageX,pageY這兩個(gè)屬性可以告訴你鼠標(biāo)是在頁面的什么位置發(fā)生的棘捣。這兩個(gè)屬性表示鼠標(biāo)在頁面上的位置辜腺,因此坐標(biāo)時(shí)相當(dāng)于頁面本身而非視口的左邊和頂邊計(jì)算的。在沒有滾動(dòng)的狀況下,pageX pageY 和clientX clientY的值相等评疗。
pageX =clientX + scrollLeft
pageY= clientY + scrollTop
screenX和screenY 相對(duì)于整個(gè)電腦屏幕的位置
offsetX offsetY:表示鼠標(biāo)相對(duì)于目標(biāo)元素邊界的坐標(biāo)(僅IE支持)
滾輪事件
mousewheel:這個(gè)事件可以在任何元素上觸發(fā)测砂。當(dāng)用戶通過鼠標(biāo)滾輪與頁面上交互,在垂直方向上滾動(dòng)頁面時(shí)就會(huì)觸發(fā)百匆。特有屬性wheelDelta 砌些。當(dāng)用戶向上滾動(dòng)時(shí)wheelDelta是120的倍數(shù),當(dāng)用戶向下滾動(dòng)時(shí)wheelDelta是-120的倍數(shù)加匈。通過wheelDelta的正負(fù)號(hào)就可以知道鼠標(biāo)滾輪的滾動(dòng)方向存璃。
觸摸設(shè)備
在面向iPhone和iPod中的Safari開發(fā)時(shí)需要注意:
1.不支持dblclick,雙擊瀏覽器窗口會(huì)放大畫面
2.兩個(gè)手指放在屏幕上且頁面隨著手指的移動(dòng)而滾動(dòng)時(shí)雕拼,會(huì)觸發(fā)mouseWheel和scroll事件
3.mousemove事件也會(huì)觸發(fā)mouseover和mouseout事件
鍵盤事件
- keydown 當(dāng)用戶按下鍵盤上任意鍵的時(shí)候觸發(fā)纵东,如果按住不放,會(huì)重復(fù)觸發(fā)
- keypress 當(dāng)用戶按下鍵盤上字符鍵的時(shí)候觸發(fā)啥寇,如果按住不放篮迎,會(huì)重復(fù)觸發(fā)
- keyup 當(dāng)用戶釋放鍵盤上的鍵的時(shí)候觸發(fā)
在發(fā)生keydown和keyup事件時(shí),event對(duì)象的keyCode會(huì)包含一個(gè)代碼示姿。event.keyCode - keyCode:按下鍵的字符編碼
文本事件
textInput事件:主要是對(duì)keypress事件補(bǔ)充。用意是將文本顯示給用戶之前更容易攔截文本逊笆。在文本插入文本框之前會(huì)觸發(fā)textInput事件栈戳。包含data屬性,保存用戶輸入輸入的字符难裆。
HTML5事件
contextmenu
beforeunload
DOMContentLoaded