JavaScript 鼠標(biāo)事件

2023-03-20 15:47 更新

鼠標(biāo)事件的種類

鼠標(biāo)事件主要有下面這些,所有事件都繼承了MouseEvent接口(詳見后文)。

(1)點(diǎn)擊事件

鼠標(biāo)點(diǎn)擊相關(guān)的有四個事件。

  • click:按下鼠標(biāo)(通常是按下主按鈕)時觸發(fā)。
  • dblclick:在同一個元素上雙擊鼠標(biāo)時觸發(fā)。
  • mousedown:按下鼠標(biāo)鍵時觸發(fā)。
  • mouseup:釋放按下的鼠標(biāo)鍵時觸發(fā)。

click事件可以看成是兩個事件組成的:用戶在同一個位置先觸發(fā)mousedown,再觸發(fā)mouseup。因此,觸發(fā)順序是,mousedown首先觸發(fā),mouseup接著觸發(fā),click最后觸發(fā)。

雙擊時,dblclick事件則會在mousedown、mouseupclick之后觸發(fā)。

(2)移動事件

鼠標(biāo)移動相關(guān)的有五個事件。

  • mousemove:當(dāng)鼠標(biāo)在一個節(jié)點(diǎn)內(nèi)部移動時觸發(fā)。當(dāng)鼠標(biāo)持續(xù)移動時,該事件會連續(xù)觸發(fā)。為了避免性能問題,建議對該事件的監(jiān)聽函數(shù)做一些限定,比如限定一段時間內(nèi)只能運(yùn)行一次。
  • mouseenter:鼠標(biāo)進(jìn)入一個節(jié)點(diǎn)時觸發(fā),進(jìn)入子節(jié)點(diǎn)不會觸發(fā)這個事件(詳見后文)。
  • mouseover:鼠標(biāo)進(jìn)入一個節(jié)點(diǎn)時觸發(fā),進(jìn)入子節(jié)點(diǎn)會再一次觸發(fā)這個事件(詳見后文)。
  • mouseout:鼠標(biāo)離開一個節(jié)點(diǎn)時觸發(fā),離開父節(jié)點(diǎn)也會觸發(fā)這個事件(詳見后文)。
  • mouseleave:鼠標(biāo)離開一個節(jié)點(diǎn)時觸發(fā),離開父節(jié)點(diǎn)不會觸發(fā)這個事件(詳見后文)。

mouseover事件和mouseenter事件,都是鼠標(biāo)進(jìn)入一個節(jié)點(diǎn)時觸發(fā)。兩者的區(qū)別是,mouseenter事件只觸發(fā)一次,而只要鼠標(biāo)在節(jié)點(diǎn)內(nèi)部移動,mouseover事件會在子節(jié)點(diǎn)上觸發(fā)多次。

/* HTML 代碼如下
 <ul>
   <li>item 1</li>
   <li>item 2</li>
   <li>item 3</li>
 </ul>
*/

var ul = document.querySelector('ul');

// 進(jìn)入 ul 節(jié)點(diǎn)以后,mouseenter 事件只會觸發(fā)一次
// 以后只要鼠標(biāo)在節(jié)點(diǎn)內(nèi)移動,都不會再觸發(fā)這個事件
// event.target 是 ul 節(jié)點(diǎn)
ul.addEventListener('mouseenter', function (event) {
  event.target.style.color = 'purple';
  setTimeout(function () {
    event.target.style.color = '';
  }, 500);
}, false);

// 進(jìn)入 ul 節(jié)點(diǎn)以后,只要在子節(jié)點(diǎn)上移動,mouseover 事件會觸發(fā)多次
// event.target 是 li 節(jié)點(diǎn)
ul.addEventListener('mouseover', function (event) {
  event.target.style.color = 'orange';
  setTimeout(function () {
    event.target.style.color = '';
  }, 500);
}, false);

上面代碼中,在父節(jié)點(diǎn)內(nèi)部進(jìn)入子節(jié)點(diǎn),不會觸發(fā)mouseenter事件,但是會觸發(fā)mouseover事件。

mouseout事件和mouseleave事件,都是鼠標(biāo)離開一個節(jié)點(diǎn)時觸發(fā)。兩者的區(qū)別是,在父元素內(nèi)部離開一個子元素時,mouseleave事件不會觸發(fā),而mouseout事件會觸發(fā)。

/* HTML 代碼如下
 <ul>
   <li>item 1</li>
   <li>item 2</li>
   <li>item 3</li>
 </ul>
*/

var ul = document.querySelector('ul');

// 先進(jìn)入 ul 節(jié)點(diǎn),然后在節(jié)點(diǎn)內(nèi)部移動,不會觸發(fā) mouseleave 事件
// 只有離開 ul 節(jié)點(diǎn)時,觸發(fā)一次 mouseleave
// event.target 是 ul 節(jié)點(diǎn)
ul.addEventListener('mouseleave', function (event) {
  event.target.style.color = 'purple';
  setTimeout(function () {
    event.target.style.color = '';
  }, 500);
}, false);

// 先進(jìn)入 ul 節(jié)點(diǎn),然后在節(jié)點(diǎn)內(nèi)部移動,mouseout 事件會觸發(fā)多次
// event.target 是 li 節(jié)點(diǎn)
ul.addEventListener('mouseout', function (event) {
  event.target.style.color = 'orange';
  setTimeout(function () {
    event.target.style.color = '';
  }, 500);
}, false);

上面代碼中,在父節(jié)點(diǎn)內(nèi)部離開子節(jié)點(diǎn),不會觸發(fā)mouseleave事件,但是會觸發(fā)mouseout事件。

(3)其他事件

  • contextmenu:按下鼠標(biāo)右鍵時(上下文菜單出現(xiàn)前)觸發(fā),或者按下“上下文”菜單鍵時觸發(fā)。
  • wheel:滾動鼠標(biāo)的滾輪時觸發(fā),該事件繼承的是WheelEvent接口。

MouseEvent 接口

MouseEvent接口代表了鼠標(biāo)相關(guān)的事件,單擊(click)、雙擊(dblclick)、松開鼠標(biāo)鍵(mouseup)、按下鼠標(biāo)鍵(mousedown)等動作,所產(chǎn)生的事件對象都是MouseEvent實(shí)例。此外,滾輪事件和拖拉事件也是MouseEvent實(shí)例。

MouseEvent接口繼承了Event接口,所以擁有Event的所有屬性和方法,并且還提供鼠標(biāo)獨(dú)有的屬性和方法。

瀏覽器原生提供一個MouseEvent()構(gòu)造函數(shù),用于新建一個MouseEvent實(shí)例。

var event = new MouseEvent(type, options);

MouseEvent()構(gòu)造函數(shù)接受兩個參數(shù)。第一個參數(shù)是字符串,表示事件名稱;第二個參數(shù)是一個事件配置對象,該參數(shù)可選。除了Event接口的實(shí)例配置屬性,該對象可以配置以下屬性,所有屬性都是可選的。

  • screenX:數(shù)值,鼠標(biāo)相對于屏幕的水平位置(單位像素),默認(rèn)值為0,設(shè)置該屬性不會移動鼠標(biāo)。
  • screenY:數(shù)值,鼠標(biāo)相對于屏幕的垂直位置(單位像素),其他與screenX相同。
  • clientX:數(shù)值,鼠標(biāo)相對于程序窗口的水平位置(單位像素),默認(rèn)值為0,設(shè)置該屬性不會移動鼠標(biāo)。
  • clientY:數(shù)值,鼠標(biāo)相對于程序窗口的垂直位置(單位像素),其他與clientX相同。
  • ctrlKey:布爾值,是否同時按下了 Ctrl 鍵,默認(rèn)值為false
  • shiftKey:布爾值,是否同時按下了 Shift 鍵,默認(rèn)值為false。
  • altKey:布爾值,是否同時按下 Alt 鍵,默認(rèn)值為false。
  • metaKey:布爾值,是否同時按下 Meta 鍵,默認(rèn)值為false。
  • button:數(shù)值,表示按下了哪一個鼠標(biāo)按鍵,默認(rèn)值為0,表示按下主鍵(通常是鼠標(biāo)的左鍵)或者當(dāng)前事件沒有定義這個屬性;1表示按下輔助鍵(通常是鼠標(biāo)的中間鍵),2表示按下次要鍵(通常是鼠標(biāo)的右鍵)。
  • buttons:數(shù)值,表示按下了鼠標(biāo)的哪些鍵,是一個三個比特位的二進(jìn)制值,默認(rèn)為0(沒有按下任何鍵)。1(二進(jìn)制001)表示按下主鍵(通常是左鍵),2(二進(jìn)制010)表示按下次要鍵(通常是右鍵),4(二進(jìn)制100)表示按下輔助鍵(通常是中間鍵)。因此,如果返回3(二進(jìn)制011)就表示同時按下了左鍵和右鍵。
  • relatedTarget:節(jié)點(diǎn)對象,表示事件的相關(guān)節(jié)點(diǎn),默認(rèn)為null。mouseentermouseover事件時,表示鼠標(biāo)剛剛離開的那個元素節(jié)點(diǎn);mouseoutmouseleave事件時,表示鼠標(biāo)正在進(jìn)入的那個元素節(jié)點(diǎn)。

下面是一個例子。

function simulateClick() {
  var event = new MouseEvent('click', {
    'bubbles': true,
    'cancelable': true
  });
  var cb = document.getElementById('checkbox');
  cb.dispatchEvent(event);
}

上面代碼生成一個鼠標(biāo)點(diǎn)擊事件,并觸發(fā)該事件。

MouseEvent 接口的實(shí)例屬性

MouseEvent.altKey,MouseEvent.ctrlKey,MouseEvent.metaKey,MouseEvent.shiftKey #

MouseEvent.altKey、MouseEvent.ctrlKeyMouseEvent.metaKey、MouseEvent.shiftKey這四個屬性都返回一個布爾值,表示事件發(fā)生時,是否按下對應(yīng)的鍵。它們都是只讀屬性。

  • altKey屬性:Alt 鍵
  • ctrlKey屬性:Ctrl 鍵
  • metaKey屬性:Meta 鍵(Mac 鍵盤是一個四瓣的小花,Windows 鍵盤是 Windows 鍵)
  • shiftKey屬性:Shift 鍵
// HTML 代碼如下
// <body onclick="showKey(event)">
function showKey(e) {
  console.log('ALT key pressed: ' + e.altKey);
  console.log('CTRL key pressed: ' + e.ctrlKey);
  console.log('META key pressed: ' + e.metaKey);
  console.log('SHIFT key pressed: ' + e.shiftKey);
}

上面代碼中,點(diǎn)擊網(wǎng)頁會輸出是否同時按下對應(yīng)的鍵。

MouseEvent.button,MouseEvent.buttons

MouseEvent.button屬性返回一個數(shù)值,表示事件發(fā)生時按下了鼠標(biāo)的哪個鍵。該屬性只讀。

  • 0:按下主鍵(通常是左鍵),或者該事件沒有初始化這個屬性(比如mousemove事件)。
  • 1:按下輔助鍵(通常是中鍵或者滾輪鍵)。
  • 2:按下次鍵(通常是右鍵)。
// HTML 代碼為
// <button onmouseup="whichButton(event)">點(diǎn)擊</button>
var whichButton = function (e) {
  switch (e.button) {
    case 0:
      console.log('Left button clicked.');
      break;
    case 1:
      console.log('Middle button clicked.');
      break;
    case 2:
      console.log('Right button clicked.');
      break;
    default:
      console.log('Unexpected code: ' + e.button);
  }
}

MouseEvent.buttons屬性返回一個三個比特位的值,表示同時按下了哪些鍵。它用來處理同時按下多個鼠標(biāo)鍵的情況。該屬性只讀。

  • 1:二進(jìn)制為001(十進(jìn)制的1),表示按下左鍵。
  • 2:二進(jìn)制為010(十進(jìn)制的2),表示按下右鍵。
  • 4:二進(jìn)制為100(十進(jìn)制的4),表示按下中鍵或滾輪鍵。

同時按下多個鍵的時候,每個按下的鍵對應(yīng)的比特位都會有值。比如,同時按下左鍵和右鍵,會返回3(二進(jìn)制為011)。

MouseEvent.clientX,MouseEvent.clientY

MouseEvent.clientX屬性返回鼠標(biāo)位置相對于瀏覽器窗口左上角的水平坐標(biāo)(單位像素),MouseEvent.clientY屬性返回垂直坐標(biāo)。這兩個屬性都是只讀屬性。

// HTML 代碼為
// <body onmousedown="showCoords(event)">
function showCoords(evt){
  console.log(
    'clientX value: ' + evt.clientX + '\n' +
    'clientY value: ' + evt.clientY + '\n'
  );
}

這兩個屬性還分別有一個別名MouseEvent.xMouseEvent.y。

MouseEvent.movementX,MouseEvent.movementY

MouseEvent.movementX屬性返回當(dāng)前位置與上一個mousemove事件之間的水平距離(單位像素)。數(shù)值上,它等于下面的計(jì)算公式。

currentEvent.movementX = currentEvent.screenX - previousEvent.screenX

MouseEvent.movementY屬性返回當(dāng)前位置與上一個mousemove事件之間的垂直距離(單位像素)。數(shù)值上,它等于下面的計(jì)算公式。

currentEvent.movementY = currentEvent.screenY - previousEvent.screenY。

這兩個屬性都是只讀屬性。

MouseEvent.screenX,MouseEvent.screenY

MouseEvent.screenX屬性返回鼠標(biāo)位置相對于屏幕左上角的水平坐標(biāo)(單位像素),MouseEvent.screenY屬性返回垂直坐標(biāo)。這兩個屬性都是只讀屬性。

// HTML 代碼如下
// <body onmousedown="showCoords(event)">
function showCoords(evt) {
  console.log(
    'screenX value: ' + evt.screenX + '\n',
    'screenY value: ' + evt.screenY + '\n'
  );
}

MouseEvent.offsetX,MouseEvent.offsetY

MouseEvent.offsetX屬性返回鼠標(biāo)位置與目標(biāo)節(jié)點(diǎn)左側(cè)的padding邊緣的水平距離(單位像素),MouseEvent.offsetY屬性返回與目標(biāo)節(jié)點(diǎn)上方的padding邊緣的垂直距離。這兩個屬性都是只讀屬性。

/* HTML 代碼如下
  <style>
    p {
      width: 100px;
      height: 100px;
      padding: 100px;
    }
  </style>
  <p>Hello</p>
*/
var p = document.querySelector('p');
p.addEventListener(
  'click',
  function (e) {
    console.log(e.offsetX);
    console.log(e.offsetY);
  },
  false
);

上面代碼中,鼠標(biāo)如果在p元素的中心位置點(diǎn)擊,會返回150 150。因此中心位置距離左側(cè)和上方的padding邊緣,等于padding的寬度(100像素)加上元素內(nèi)容區(qū)域一半的寬度(50像素)。

MouseEvent.pageX,MouseEvent.pageY

MouseEvent.pageX屬性返回鼠標(biāo)位置與文檔左側(cè)邊緣的距離(單位像素),MouseEvent.pageY屬性返回與文檔上側(cè)邊緣的距離(單位像素)。它們的返回值都包括文檔不可見的部分。這兩個屬性都是只讀。

/* HTML 代碼如下
  <style>
    body {
      height: 2000px;
    }
  </style>
*/
document.body.addEventListener(
  'click',
  function (e) {
    console.log(e.pageX);
    console.log(e.pageY);
  },
  false
);

上面代碼中,頁面高度為2000像素,會產(chǎn)生垂直滾動條。滾動到頁面底部,點(diǎn)擊鼠標(biāo)輸出的pageY值會接近2000。

MouseEvent.relatedTarget

MouseEvent.relatedTarget屬性返回事件的相關(guān)節(jié)點(diǎn)。對于那些沒有相關(guān)節(jié)點(diǎn)的事件,該屬性返回null。該屬性只讀。

下表列出不同事件的target屬性值和relatedTarget屬性值義。

事件名稱 target 屬性 relatedTarget 屬性
focusin 接受焦點(diǎn)的節(jié)點(diǎn) 喪失焦點(diǎn)的節(jié)點(diǎn)
focusout 喪失焦點(diǎn)的節(jié)點(diǎn) 接受焦點(diǎn)的節(jié)點(diǎn)
mouseenter 將要進(jìn)入的節(jié)點(diǎn) 將要離開的節(jié)點(diǎn)
mouseleave 將要離開的節(jié)點(diǎn) 將要進(jìn)入的節(jié)點(diǎn)
mouseout 將要離開的節(jié)點(diǎn) 將要進(jìn)入的節(jié)點(diǎn)
mouseover 將要進(jìn)入的節(jié)點(diǎn) 將要離開的節(jié)點(diǎn)
dragenter 將要進(jìn)入的節(jié)點(diǎn) 將要離開的節(jié)點(diǎn)
dragexit 將要離開的節(jié)點(diǎn) 將要進(jìn)入的節(jié)點(diǎn)

下面是一個例子。

/*
  HTML 代碼如下
  <div id="outer" style="height:50px;width:50px;border:1px solid black;">
    <div id="inner" style="height:25px;width:25px;border:1px solid black;"></div>
  </div>
*/

var inner = document.getElementById('inner');
inner.addEventListener('mouseover', function (event) {
  console.log('進(jìn)入' + event.target.id + ' 離開' + event.relatedTarget.id);
}, false);
inner.addEventListener('mouseenter', function (event) {
  console.log('進(jìn)入' + event.target.id + ' 離開' + event.relatedTarget.id);
});
inner.addEventListener('mouseout', function (event) {
  console.log('離開' + event.target.id + ' 進(jìn)入' + event.relatedTarget.id);
});
inner.addEventListener("mouseleave", function (event){
  console.log('離開' + event.target.id + ' 進(jìn)入' + event.relatedTarget.id);
});

// 鼠標(biāo)從 outer 進(jìn)入inner,輸出
// 進(jìn)入inner 離開outer
// 進(jìn)入inner 離開outer

// 鼠標(biāo)從 inner進(jìn)入 outer,輸出
// 離開inner 進(jìn)入outer
// 離開inner 進(jìn)入outer

MouseEvent 接口的實(shí)例方法

MouseEvent.getModifierState()

MouseEvent.getModifierState方法返回一個布爾值,表示有沒有按下特定的功能鍵。它的參數(shù)是一個表示功能鍵的字符串。

document.addEventListener('click', function (e) {
  console.log(e.getModifierState('CapsLock'));
}, false);

上面的代碼可以了解用戶是否按下了大寫鍵。

WheelEvent 接口

概述

WheelEvent 接口繼承了 MouseEvent 實(shí)例,代表鼠標(biāo)滾輪事件的實(shí)例對象。目前,鼠標(biāo)滾輪相關(guān)的事件只有一個wheel事件,用戶滾動鼠標(biāo)的滾輪,就生成這個事件的實(shí)例。

瀏覽器原生提供WheelEvent()構(gòu)造函數(shù),用來生成WheelEvent實(shí)例。

var wheelEvent = new WheelEvent(type, options);

WheelEvent()構(gòu)造函數(shù)可以接受兩個參數(shù),第一個是字符串,表示事件類型,對于滾輪事件來說,這個值目前只能是wheel。第二個參數(shù)是事件的配置對象。該對象的屬性除了Event、UIEvent的配置屬性以外,還可以接受以下幾個屬性,所有屬性都是可選的。

  • deltaX:數(shù)值,表示滾輪的水平滾動量,默認(rèn)值是 0.0。
  • deltaY:數(shù)值,表示滾輪的垂直滾動量,默認(rèn)值是 0.0。
  • deltaZ:數(shù)值,表示滾輪的 Z 軸滾動量,默認(rèn)值是 0.0。
  • deltaMode:數(shù)值,表示相關(guān)的滾動事件的單位,適用于上面三個屬性。0表示滾動單位為像素,1表示單位為行,2表示單位為頁,默認(rèn)為0。

實(shí)例屬性

WheelEvent事件實(shí)例除了具有EventMouseEvent的實(shí)例屬性和實(shí)例方法,還有一些自己的實(shí)例屬性,但是沒有自己的實(shí)例方法。

下面的屬性都是只讀屬性。

  • WheelEvent.deltaX:數(shù)值,表示滾輪的水平滾動量。
  • WheelEvent.deltaY:數(shù)值,表示滾輪的垂直滾動量。
  • WheelEvent.deltaZ:數(shù)值,表示滾輪的 Z 軸滾動量。
  • WheelEvent.deltaMode:數(shù)值,表示上面三個屬性的單位,0是像素,1是行,2是頁。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號