前面的話
鼠標事件是web開發中最常用的一類事件,畢竟鼠標是最主要的定位設備。本文將詳細介紹鼠標事件的內容
類型
鼠標事件共10類,包括click、contextmenu、dblclick、mousedown、mouseup、mousemove、mouseover、mouseout、mouseenter和mouseleave
click 當用戶按下并釋放鼠標按鍵或其他方式“激活”元素時觸發
contextmenu 可以取消的事件,當上下文菜單即將出現時觸發。當前瀏覽器在鼠標右擊時顯示上下文菜單
dblclick 當用戶雙擊鼠標時觸發
mousedown 當用戶按下鼠標按鍵時觸發
mouseup 當用戶釋放鼠標按鍵時觸發
mousemove 當用戶移動鼠標時觸發
mouseover 當鼠標進入元素時觸發。relatedTarget(在IE中是fromElement)指的是鼠標來自的元素
mouseout 當鼠標離開元素時觸發。relatedTarget(在IE中是toElement)指的是鼠標要去往的元素
mouseenter 類似mouseover,但不冒泡。IE將其引入,HTML5將其標準化,但尚未廣泛實現
mouseleave 類似mouseout,但不冒泡。IE將其引入,HTML5將其標準化,但尚未廣泛實現
冒泡
頁面上的所有元素都支持鼠標事件,除了mouseenter和mouseleave事件外,所有的鼠標事件都會冒泡
[注意]safari瀏覽器不支持mouseenter和mouseleave事件
<button id="test" style="height: 30px;width: 200px;"></button> <script> //鼠標移入移出按鈕時,顯示false,表示不冒泡 test.onmouseenter = test.onmouseleave =function(e){ test.innerHTML += e.bubbles;//false } </script>
<button id="test" style="height: 30px;width: 200px;"></button> <script> //鼠標移入移出按鈕時,顯示true,表示冒泡 test.onmouseover = test.onmouseout =function(e){ test.innerHTML += e.bubbles;//true } </script>
順序
【1】鼠標移入時,觸發mouseover、mouseenter和mousemove事件
IE瀏覽器會先觸發一次mousemove事件,再觸發mouseover和mouseenter事件,再觸發多次mousemove事件
而其他瀏覽器都是先觸發mouseover和mouseenter事件,再觸發多次mousemove事件
<div id="box" style="height:30px;width:200px;background:pink;"></div> <button id="reset">還原</button> <script> reset.onclick = function(){history.go();} var oBox = document.getElementById('box'); oBox.onmouseover = oBox.onmouseenter=oBox.onmousemove =function(e){ e = e || event; box.innerHTML += e.type+ ';'; } </script>
【2】鼠標移出時,觸發mousemove、mouseleave和mouseout事件
所有瀏覽器的順序都是(1)mousemove、(2)mouseout和(3)mouseleave事件
<div id="box" style="height:30px;width:200px;background:pink;"></div> <button id="reset">還原</button> <script> reset.onclick = function(){history.go();} var oBox = document.getElementById('box'); oBox.onmouseleave = oBox.onmouseout=oBox.onmousemove =function(e){ e = e || event; box.innerHTML += e.type+ ';'; } </script>
【3】雙擊鼠標時,觸發mousedown、mouseup、click、dblclick事件
一般地,瀏覽器的順序是(1)mousedown、(2)mouseup、(3)click、(4)mousedown、(5)mouseup、(6)click、(7)dblclick
但IE8-瀏覽器有一個小bug,在雙擊事件中,它會跳過第二個mousedown和click事件,順序為(1)mousedown、(2)mouseup、(3)click、(4)mouseup、(5)dblclick
<div id="box" style="height:30px;width:200px;background:pink;"></div> <button id="reset">還原</button> <script> reset.onclick = function(){history.go();} var oBox = document.getElementById('box'); oBox.onclick = oBox.ondblclick = oBox.onmousedown = oBox.onmouseup=function(e){ e = e || event; box.innerHTML += e.type+ ';'; } </script>
【4】點擊鼠標右鍵時,觸發mousedown、mouseup、contextmenu事件
一般地,瀏覽器的順序是(1)mousedown、(2)mouseup、(3)contextmenu
但safari瀏覽器有一個小bug,它不觸發mouseup事件,順序為(1)mousedown、(2)contextmenu
<div id="box" style="height:30px;width:200px;background:pink;"></div> <button id="reset">還原</button> <script> reset.onclick = function(){history.go();} var oBox = document.getElementById('box'); oBox.oncontextmenu = oBox.onmousedown = oBox.onmouseup=function(e){ e = e || event; box.innerHTML += e.type+ ';'; } </script>
【5】嵌套元素的移入移出時,觸發mouseover、mouseenter、mouseleave、mouseout事件
從父級元素進入子級元素時,順序為:(1)父級元素的mouseout、(2)子級元素的mouseover、(3)父級元素的mouseover、(4)子級元素的mouseenter
從子級元素進入父級元素時,順序為:(1)子級元素的mouseout、(2)父級元素的mouseout、(3)子級元素的mouseleave、(4)父級元素的mouseover
<div id="box" style="padding: 50px;width: 100px;background:pink;"> <div id="inner" style="height: 100px;width: 100px;background-color: lightblue;"></div> </div> <button id="reset">還原</button> <script> reset.onclick = function(){history.go();} inner.onmouseout=inner.onmouseleave=inner.onmouseover=inner.onmouseenter=box.onmouseout=box.onmouseleave=box.onmouseover=box.onmouseenter= function(e){ inner.innerHTML += e.currentTarget.id.slice(0,1) + ':' +e.type.slice(5) + ';'; } </script>
從上面的結果可以看出mouseover、mouseout和mouseleave、mouseenter事件的區別
1、mouseover、mouseout是冒泡的,而mouseleave和mouseenter是不冒泡的
2、從父級元素進入子級元素時,不會觸發父級元素的mouseleave事件
3、從子級元素進入父級元素時,不會觸發父級元素的mouseenter事件
事件對象
鼠標事件對象提供了豐富的信息,接下來將按照功能分類介紹
坐標位置
關于坐標位置,事件對象提供了clientX/Y、pageX/Y、screenX/Y、x/y、offsetX/Y、layerX/Y這6對信息
clientX/Y與x/y
clientX/Y表示鼠標指針在可視區域中的水平和垂直坐標
x/y與clientX/Y相同,但有兼容問題。firefox瀏覽器不支持x/y,且IE7-瀏覽器把視口的左上角坐標設置為(2,2),其他瀏覽器則將(0,0)作為起點坐標,所以存在(2,2)的差距
<div id="box" style="height:100px;width:200px;background:pink;"></div> <script> box.onmousemove=function(e){ e = e || event; box.innerHTML = 'clientX:' + e.clientX +';clientY:'+e.clientY + '<br>x:' + e.x + ';y:' + e.y; } </script>
screenX/Y
screenX/Y表示鼠標指針相對于屏幕的水平和垂直坐標
<div id="box" style="height:100px;width:200px;background:pink;"></div> <script> box.onmousemove=function(e){ e = e || event; box.innerHTML = 'clientX:' + e.clientX +';clientY:'+e.clientY + '<br>screenX:' + e.screenX + ';screenY:' + e.screenY; } </script>
pageX/Y與layerX/Y
pageX/Y表示相對于頁面的水平和垂直坐標,它與clientX/clientY的區別是不隨滾動條的位置變化
layerX/Y與pageX/Y相同
<body style="height:2000px;"> <div id="box" style="height:100px;width:300px;background:pink;"></div> <div id="result"></div> <script> var oBox = document.getElementById('box'); oBox.onmousemove=function(e){ e = e || event; result.innerHTML = 'clientX:' + e.clientX +';clientY:'+e.clientY + '<br>pageX:' + e.pageX + ';pageY:' + e.pageY; } </script> </body>
[注意]IE8-瀏覽器不支持pageX/Y和layerX/Y,不過可以根據scrollTop/Left和clientX/Y計算出來
兼容
handler = function(e){
e = e || event;
if(e.pageX == undefined){
e.pageX = e.clientX + document.documentElement.scrollLeft
}
if(e.pageY == undefined){
e.pageY = e.clientY + document.documentElement.scrollTop
}
}
offsetX/Y
offsetX/Y表示相對于定位父級的水平和垂直坐標
當頁面無定位元素時,body是元素的定位父級。由于body的默認margin是8px,所以offsetX/Y與clientX/Y差(8,8)
<div id="box" style="height:100px;width:300px;background:pink;"></div> <script> var oBox = document.getElementById('box'); oBox.onmousemove=function(e){ e = e || event; oBox.innerHTML = 'clientX:' + e.clientX +';clientY:'+e.clientY + '<br>offsetX:' + e.offsetX + ';offsetY:' + e.offsetY; } </script>
修改鍵
雖然鼠標事件主要是使用鼠標來觸發的,但在按下鼠標時鍵盤上的某些鍵的狀態也可以影響到所要采取的操作
這些修改鍵就是Shift、Ctrl、Alt和Meta(在Windows鍵盤中是Windows鍵,在蘋果機中是Cmd鍵),它們經常被用來修改鼠標事件的行為
DOM為此規定了4個屬性,表示這些修改鍵的狀態:shiftKey、ctrlKey、altKey和metaKey。這些屬性中包含的都是布爾值,如果相應的鍵被按下了,則值為true;否則值為false
[注意]IE8-瀏覽器不支持metaKey屬性
下面通過點擊事件,來測試是否在點擊的時候按下了這些修改鍵
<div id="box" style="height:30px;width:300px;background:pink;"></div> <script> box.onclick=function(e){ e = e || event; box.innerHTML = ''; if(e.shiftKey){box.innerHTML += 'shiftKey;'} if(e.ctrlKey){box.innerHTML += 'ctrlKey;'} if(e.altKey){box.innerHTML += 'altKey;'} if(e.metaKey){box.innerHTML += 'metaKey;'} } </script>
相關元素
relatedTarget屬性返回事件的次要相關節點。對于那些沒有次要相關節點的事件,該屬性返回null
對mouseover事件而言,事件的主目標target是獲得光標的元素,而相關元素relatedTarget就是那個失去光標的元素
下表列出不同事件的target屬性和relatedTarget屬性含義
事件名稱 target屬性 relatedTarget屬性
focusin 接受焦點的節點 喪失焦點的節點
focusout 喪失焦點的節點 接受焦點的節點
mouseenter 將要進入的節點 將要離開的節點
mouseleave 將要離開的節點 將要進入的節點
mouseout 將要離開的節點 將要進入的節點
mouseover 將要進入的節點 將要離開的節點
dragenter 將要進入的節點 將要離開的節點
dragexit 將要離開的節點 將要進入的節點
IE8-瀏覽器不支持target和relatedTarget屬性
兼容
target可以用srcElement屬性替代,relatedTarget可以用toElement屬性替代
[注意]firefox瀏覽器不支持srcElement和toElement屬性
下列代碼中, div元素的mouseover事件是從<body>移入到<div>中
<div id="box" style="height:100px;width:400px;background:pink;"></div> <button id="reset">還原</button> <script> reset.onclick = function(){history.go();} box.onmouseover=function(e){ e = e || event; box.innerHTML = 'target:' + (e.target||e.srcElement) +'<br>relatedTarget:'+(e.relatedTarget||e.toElement) ; } </script>
鼠標按鍵
button和buttons屬性返回事件鼠標按鍵信息
button
button屬性返回一個數值,表示按下了鼠標哪個鍵
[注意]若不阻止右鍵默認行為,safari瀏覽器無法表示按下右鍵
-1 表示沒有按下按鍵
0 表示按下左鍵
1 表示按下滾輪
2 表示按下右鍵
buttons
buttons屬性返回一個3個比特位的值,表示同時按下了哪些鍵。它用來處理同時按下多個鼠標鍵的情況
[注意]safari瀏覽器不支持buttons屬性
1 二進制為001,表示按下左鍵
2 二進制為010,表示按下右鍵
4 二進制為100,表示按下滾輪
所以,同時按下左鍵和右鍵,buttons的二進制為011,表示3;同時按下左鍵和滾輪,buttons的二進制為101,表示5;同時按下右鍵和滾輪,buttons的二進制為110,表示6
<div id="box" style="height:30px;width:200px;background:pink;"></div> <script> box.onmouseup=function(e){ e = e || event; box.innerHTML = 'button:' + e.button + ';buttons:' + e.buttons; } </script>
但,IE8-瀏覽器的button屬性的值與標準的button屬性有很大差異
0:表示沒有按下按鈕
1:表示按下了左鍵
2:表示按下了右鍵
3:表示同時按下了左、右鍵
4:表示按下了滾輪
5:表示同時按下了左鍵和滾輪
6:表示同時按下了右鍵和滾輪
7:表示同時按下了左鍵、右鍵和滾輪
兼容
此時,無法使用能力檢測來確定差異,可以通過hasFeature()方法來檢測,關于hasFeature()方法的詳細信息移步至此
var hasMouse = document.implementation.hasFeature('MouseEvents','2.0'); //IE8-瀏覽器返回false,其他瀏覽器true console.log(hasMouse);
<div id="box" style="height:30px;width:200px;background:pink;"></div> <script> box.onmouseup=function(e){ e = e || event; var Compatiblebutton; //IE8-瀏覽器 if(!document.implementation.hasFeature('MouseEvents','2.0')){ switch(e.button){ case 1: Compatiblebutton = 0; break; case 2: Compatiblebutton = 2; break; case 4: Compatiblebutton = 1; break; } }else{ Compatiblebutton = e.button; } box.innerHTML = 'button:' + Compatiblebutton; } </script>
滾輪事件
對于滾輪事件,有類似的滾動事件scroll,但是滾動事件不兼容IE8-瀏覽器,詳細情況移步至此
滾輪事件與滾動事件不同,滾動事件必須有滾動條,才可以實現。而滾動事件是滾動鼠標滾輪觸發的事件,與是否有滾動條無關
IE6首先實現了鼠標滾輪mousewheel事件,當用戶通過滾動與頁面交互、在垂直方向上滾動頁面時,會觸發mousewheel事件。最終會冒泡到document(IE8-)或window(標準)
[注意]這個事件可以在任何元素上觸發
滾輪事件中有一個wheelDelta屬性,當用戶向前滾動鼠標滾輪時,wheelDelta是120的倍數;當用戶向后滾動鼠標滾輪時,wheelDelta是-120的倍數
<div id="box" style="height:100px;width:200px;background:pink;"></div> <script> box.onmousewheel=function(e){ e = e || event; box.innerHTML = e.wheelDelta; if(e.wheelDelta >0){ box.style.backgroundColor = 'lightblue'; }else{ box.style.backgroundColor = 'lightgreen'; } } </script>
firefox瀏覽器不支持mousewheel事件,它支持DOMMouseScroll事件,而有關鼠標滾輪的信息則保存在detail屬性中,當向前滾動鼠標滾輪時,這個屬性的值是-3的倍數,當向后滾動鼠標滾輪時,這個屬性的值是3的倍數
[注意]該事件僅支持DOM2級事件處理程序的寫法
<div id="box" style="height:100px;width:200px;background:pink;"></div> <script> box.addEventListener('DOMMouseScroll',function(e){ e = e || event; console.log(e) box.innerHTML = e.detail; if(e.detail >0){ box.style.backgroundColor = 'lightblue'; }else{ box.style.backgroundColor = 'lightgreen'; } }) </script>
兼容
var handler = function(e){
var getWheelDelta;
e = e || event;
if(e.wheelDelta){
getWheelDelta = e.wheelDelta;
}else{
getWheelDelta = -e.detail * 40;
}
}
<body style="height:2000px"> <p style="position: fixed">滾動滾輪將顯示滾動值</p> <div id="test" style="position: fixed"></div> <script> var wheel = function(e){ e = e || event; if(e.wheelDelta){ test.innerHTML = e.wheelDelta; }else{ test.innerHTML = -e.detail * 40; } } document.body.onmousewheel = wheel; document.body.addEventListener('DOMMouseScroll',wheel,false); </script> </body>
移動設備
由于移動設備沒有鼠標,所以與電腦端有一些不同之處。移動設備盡量使用移動端事件,而不要使用鼠標事件
【1】不支持dblclick雙擊事件。在移動設備中雙擊瀏覽器窗口會放大畫面
【2】單擊元素會觸發mousemove事件
【3】兩個手指放在屏幕上且頁面隨手指移動而滾動時會觸發mousewheel和scroll事件
歡迎交流
文章列表