JavaScript 鼠標事件

2023-03-20 15:47 更新

鼠標事件的種類

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

(1)點擊事件

鼠標點擊相關的有四個事件。

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

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

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

(2)移動事件

鼠標移動相關的有五個事件。

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

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

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

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

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

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

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

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

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

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

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

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

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

(3)其他事件

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

MouseEvent 接口

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

MouseEvent接口繼承了Event接口,所以擁有Event的所有屬性和方法,并且還提供鼠標獨有的屬性和方法。

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

var event = new MouseEvent(type, options);

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

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

下面是一個例子。

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

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

MouseEvent 接口的實例屬性

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

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

  • 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);
}

上面代碼中,點擊網頁會輸出是否同時按下對應的鍵。

MouseEvent.button,MouseEvent.buttons

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

  • 0:按下主鍵(通常是左鍵),或者該事件沒有初始化這個屬性(比如mousemove事件)。
  • 1:按下輔助鍵(通常是中鍵或者滾輪鍵)。
  • 2:按下次鍵(通常是右鍵)。
// HTML 代碼為
// <button onmouseup="whichButton(event)">點擊</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屬性返回一個三個比特位的值,表示同時按下了哪些鍵。它用來處理同時按下多個鼠標鍵的情況。該屬性只讀。

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

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

MouseEvent.clientX,MouseEvent.clientY

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

// 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屬性返回當前位置與上一個mousemove事件之間的水平距離(單位像素)。數(shù)值上,它等于下面的計算公式。

currentEvent.movementX = currentEvent.screenX - previousEvent.screenX

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

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

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

MouseEvent.screenX,MouseEvent.screenY

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

// 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屬性返回鼠標位置與目標節(jié)點左側的padding邊緣的水平距離(單位像素),MouseEvent.offsetY屬性返回與目標節(jié)點上方的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
);

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

MouseEvent.pageX,MouseEvent.pageY

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

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

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

MouseEvent.relatedTarget

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

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

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

下面是一個例子。

/*
  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('進入' + event.target.id + ' 離開' + event.relatedTarget.id);
}, false);
inner.addEventListener('mouseenter', function (event) {
  console.log('進入' + event.target.id + ' 離開' + event.relatedTarget.id);
});
inner.addEventListener('mouseout', function (event) {
  console.log('離開' + event.target.id + ' 進入' + event.relatedTarget.id);
});
inner.addEventListener("mouseleave", function (event){
  console.log('離開' + event.target.id + ' 進入' + event.relatedTarget.id);
});

// 鼠標從 outer 進入inner,輸出
// 進入inner 離開outer
// 進入inner 離開outer

// 鼠標從 inner進入 outer,輸出
// 離開inner 進入outer
// 離開inner 進入outer

MouseEvent 接口的實例方法

MouseEvent.getModifierState()

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

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

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

WheelEvent 接口

概述

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

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

var wheelEvent = new WheelEvent(type, options);

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

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

實例屬性

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

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

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


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號