最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

前端JavaScript編寫(xiě)鼠標(biāo)事件的完整指南

 更新時(shí)間:2026年05月30日 09:14:03   作者:detayun  
鼠標(biāo)事件是Web交互的基礎(chǔ),點(diǎn)擊、拖拽、滾輪、懸停幾乎所有操作都離不開(kāi)它,本文從基礎(chǔ)到實(shí)戰(zhàn),講清楚每個(gè)事件怎么用,什么時(shí)候用,有哪些坑

鼠標(biāo)事件是Web交互的基礎(chǔ)。點(diǎn)擊、拖拽、滾輪、懸停……幾乎所有操作都離不開(kāi)它。

但很多人只會(huì)寫(xiě) onclick,其實(shí)鼠標(biāo)事件遠(yuǎn)不止這些。本文從基礎(chǔ)到實(shí)戰(zhàn),講清楚每個(gè)事件怎么用、什么時(shí)候用、有哪些坑。

一、八個(gè)核心事件對(duì)比

事件觸發(fā)時(shí)機(jī)典型用途
click完整點(diǎn)擊(按下+松開(kāi))按鈕、鏈接、提交
dblclick雙擊打開(kāi)文件、編輯文本
mousedown鼠標(biāo)按下瞬間拖拽開(kāi)始、按住觸發(fā)
mouseup鼠標(biāo)松開(kāi)瞬間拖拽結(jié)束
mousemove鼠標(biāo)移動(dòng)實(shí)時(shí)跟蹤位置、繪圖
mouseenter鼠標(biāo)進(jìn)入元素懸停顯示提示
mouseleave鼠標(biāo)離開(kāi)元素隱藏提示
wheel滾輪滾動(dòng)切換圖片、縮放
contextmenu右鍵點(diǎn)擊自定義右鍵菜單

最常用的四個(gè):click、mousedownmousemove、wheel。

二、基礎(chǔ)寫(xiě)法

// 方式1:addEventListener(推薦)
document.getElementById('btn').addEventListener('click', function(e) {
    console.log('點(diǎn)擊了');
});
// 方式2:on事件屬性(簡(jiǎn)單場(chǎng)景可用)
<button onclick="alert('點(diǎn)擊了')">點(diǎn)我</button>
// 方式3:內(nèi)聯(lián)事件(不推薦,維護(hù)性差)
<div onmouseover="this.style.background='red'">懸停變紅</div>

結(jié)論:優(yōu)先用 addEventListener,可以綁定多個(gè)事件,也方便解綁。

三、事件對(duì)象e里有什么

element.addEventListener('click', function(e) {
    console.log(e.clientX, e.clientY);  // 鼠標(biāo)相對(duì)于視口的坐標(biāo)
    console.log(e.pageX, e.pageY);      // 鼠標(biāo)相對(duì)于文檔的坐標(biāo)
    console.log(e.target);              // 觸發(fā)事件的元素
    console.log(e.button);              // 哪個(gè)鍵:0左鍵,1中鍵,2右鍵
});

clientX/Y vs pageX/Y 怎么選?

  • clientX/Y → 相對(duì)于瀏覽器窗口,不受滾動(dòng)影響
  • pageX/Y → 相對(duì)于整個(gè)文檔,包含滾動(dòng)距離

做拖拽、定位,用 clientX/Y 更方便。

四、實(shí)戰(zhàn):驗(yàn)證碼識(shí)別頁(yè)面的鼠標(biāo)交互

場(chǎng)景1:拖拽滑塊旋轉(zhuǎn)圖片

這是我們項(xiàng)目中的核心交互——按住滑塊左右拖動(dòng),圖片同步旋轉(zhuǎn)。

var box = document.getElementsByClassName("sliding_block")[0];
var isDrop = false;
var angle = 0;

// 按下:開(kāi)始拖拽
box.onmousedown = function(e) {
    var e = e || window.event;
    var x = e.clientX - box.offsetLeft;
    var y = e.clientY - box.offsetTop;
    isDrop = true;
};

// 移動(dòng):實(shí)時(shí)更新位置和角度
document.onmousemove = function(e) {
    if (!isDrop) return;
    
    var e = e || window.event;
    var moveX = e.clientX - x;
    
    // 限制范圍 0~360
    var minX = 0, maxX = 360;
    if (moveX < minX) moveX = minX;
    if (moveX > maxX) moveX = maxX;
    
    box.style.left = moveX + "px";
    angle = moveX;
    
    $("#baidu_img").attr("style", "transform: rotate(" + angle + "deg);");
    $("#msg_angle_span").html(angle);
};

// 松開(kāi):結(jié)束拖拽
document.onmouseup = function() {
    isDrop = false;
};

關(guān)鍵點(diǎn)

  • mousedown 記錄初始位置
  • mousemove 實(shí)時(shí)計(jì)算偏移
  • mouseup 結(jié)束拖拽
  • 三個(gè)事件必須配合使用,缺一不可

場(chǎng)景2:滾輪切換圖片

document.addEventListener('wheel', function(e) {
    // 避免在輸入框中觸發(fā)
    if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') {
        return;
    }
    
    e.preventDefault();  // 必須加,否則頁(yè)面會(huì)跟著滾
    
    if (e.deltaY > 0) {
        next_img();      // 滾輪向下 → 下一張
    } else {
        last_img();      // 滾輪向上 → 上一張
    }
}, { passive: false });  // passive: false 是關(guān)鍵

e.deltaY 的含義:

  • deltaY > 0 → 滾輪向下
  • deltaY < 0 → 滾輪向上
  • deltaX → 水平滾動(dòng)(橫向滾輪)

場(chǎng)景3:拖拽浮動(dòng)框

項(xiàng)目中還有個(gè)浮動(dòng)框可以自由拖動(dòng):

var floatingDiv = document.getElementById('floatingDiv');
var initialX = null, initialY = null;

floatingDiv.addEventListener('mousedown', function(e) {
    initialX = e.clientX - floatingDiv.getBoundingClientRect().left;
    initialY = e.clientY - floatingDiv.getBoundingClientRect().top;
    e.preventDefault();  // 防止選中文本
});

document.addEventListener('mousemove', function(e) {
    if (initialX === null) return;
    
    var deltaX = e.clientX - initialX;
    var deltaY = e.clientY - initialY;
    
    floatingDiv.style.left = deltaX + 'px';
    floatingDiv.style.top = deltaY + 'px';
});

document.addEventListener('mouseup', function() {
    initialX = null;
    initialY = null;
});

五、mouseenter vs mouseover 的區(qū)別

事件冒泡觸發(fā)時(shí)機(jī)推薦場(chǎng)景
mouseover? 冒泡進(jìn)入子元素也會(huì)觸發(fā)需要事件冒泡時(shí)
mouseenter? 不冒泡只在進(jìn)入自身時(shí)觸發(fā)懸停效果優(yōu)先用這個(gè)

同理:mouseleave vs mouseout,也是 mouseleave 更常用。

// ? 不推薦:進(jìn)入子元素會(huì)反復(fù)觸發(fā)
div.addEventListener('mouseover', function() {
    this.style.background = 'yellow';
});

// ? 推薦:只在進(jìn)入/離開(kāi) div 時(shí)觸發(fā)一次
div.addEventListener('mouseenter', function() {
    this.style.background = 'yellow';
});
div.addEventListener('mouseleave', function() {
    this.style.background = '';
});

六、五個(gè)常見(jiàn)坑

坑1:忘了e.preventDefault()

右鍵會(huì)彈出瀏覽器菜單,滾輪會(huì)滾動(dòng)頁(yè)面,拖拽會(huì)選中文本。

解決:在 mousedownwheel 里加 e.preventDefault()。

坑2:mousemove性能問(wèn)題

mousemove 觸發(fā)頻率極高(每秒幾十次),里面寫(xiě)重邏輯會(huì)卡頓。

解決:用 requestAnimationFrame 節(jié)流。

var ticking = false;
document.addEventListener('mousemove', function(e) {
    if (!ticking) {
        requestAnimationFrame(function() {
            // 在這里寫(xiě)業(yè)務(wù)邏輯
            ticking = false;
        });
        ticking = true;
    }
});

坑3:拖拽時(shí)元素被選中

拖拽過(guò)程中文字被藍(lán)框選中,體驗(yàn)很差。

解決:CSS 全局禁用選中。

.sliding_block {
    user-select: none;
    -webkit-user-select: none;
}

(你的代碼里已經(jīng)加了,做得很好)

坑4:事件綁定在錯(cuò)誤的元素上

mousemove 綁在滑塊上,結(jié)果拖出滑塊就失效了。

解決:mousemovemouseup 綁在 document 上,不是綁在滑塊上。

// ? 正確
box.onmousedown = function() { ... };
document.onmousemove = function() { ... };  // 綁在 document 上
document.onmouseup = function() { ... };    // 綁在 document 上

// ? 錯(cuò)誤
box.onmousemove = function() { ... };  // 鼠標(biāo)移出滑塊就失效

坑5:用onclick綁定多個(gè)事件

// ? 后面的會(huì)覆蓋前面的
btn.onclick = function() { alert(1); };
btn.onclick = function() { alert(2); };  // 只會(huì)彈出 2

// ? 用 addEventListener 可以綁定多個(gè)
btn.addEventListener('click', function() { alert(1); });
btn.addEventListener('click', function() { alert(2); });  // 兩個(gè)都會(huì)執(zhí)行

七、鼠標(biāo)事件設(shè)計(jì)原則

原則說(shuō)明
拖拽用 mousedown + mousemove + mouseup三件套,缺一不可
mousemove 綁在 document防止拖出元素失效
滾輪用 wheel + preventDefault{ passive: false } 必須加
懸停用 mouseenter/mouseleave不冒泡,不會(huì)反復(fù)觸發(fā)
第一行判斷是否在輸入框避免打字時(shí)誤觸發(fā)

總結(jié)

鼠標(biāo)事件的核心就四句話:

  1. 點(diǎn)擊用 click,拖拽用 mousedown + mousemove + mouseup
  2. 滾輪用 wheel,記得 preventDefault() + { passive: false }
  3. mousemove 綁在 document 上,不是綁在元素上
  4. 第一行判斷是否在輸入框中

掌握這四點(diǎn),你就能搞定90%的鼠標(biāo)交互需求。

到此這篇關(guān)于前端JavaScript編寫(xiě)鼠標(biāo)事件的完整指南的文章就介紹到這了,更多相關(guān)JavaScript鼠標(biāo)事件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

兴隆县| 九江县| 奉节县| 绥滨县| 蒙阴县| 郑州市| 呼和浩特市| 甘肃省| 平阳县| 兰坪| 龙游县| 阿城市| 江阴市| 芜湖县| 错那县| 东山县| 武威市| 信丰县| 育儿| 昌邑市| 秦皇岛市| 香格里拉县| 衡东县| 留坝县| 昭平县| 海南省| 湛江市| 中江县| 阳西县| 九龙坡区| 曲靖市| 巴东县| 余庆县| 高雄市| 北京市| 昌都县| 凤山县| 瑞安市| 左云县| 弥渡县| 南岸区|