首页 > js mousemove和mouseup事件到底应该注册在捕获阶段还是冒泡阶段

js mousemove和mouseup事件到底应该注册在捕获阶段还是冒泡阶段

《JavaScript权威指南》P462 例17-2 拖动文档元素的例子中

对于mousemove和mouseup事件有这样的描述

值得注意的是mousemove和mouseup处理程序注册为捕获事件处理程序。这是因为用户可能移动鼠标比其后的文档元素更快,如果这种情况发生,某些mousemove事件会发生在原始目标元素之外。没有捕获,这些事件将无法分派正确的处理程序。

但是本人经过测试,只要在触发mousedown事件之后将mousemove和mouseup注册在document对象上,就可以实现功能,无论是事件冒泡阶段还是事件捕获阶段。

document.addEventListener("mousemove", moveHandler, true);
document.addEventListener("mouseup", upHandler, true);

或者


document.addEventListener("mousemove", moveHandler, false);
document.addEventListener("mouseup", upHandler, false);

Drag.js

    function drag(elementToDrag, event){
    var scroll = getScrollOffsets();
    var startX = scroll.x + event.clientX;
    var startY = scroll.y + event.clientY;

    var oriX = elementToDrag.offsetLeft;
    var oriY = elementToDrag.offsetTop;

    var deltaX = startX - oriX;
    var deltaY = startY - oriY;

    console.log(1);

    document.addEventListener("mousemove", moveHandler, true);
    document.addEventListener("mouseup", upHandler, true);

    if(event.stopPropagation)
        event.stopPropagation();
    else
        event.cancelBubble = true;

    if(event.preventDefault)
        event.preventDefault();
    else
        event.returnValue = false;


    function moveHandler(e){
        var scroll = getScrollOffsets();
        elementToDrag.style.left = (e.clientX + scroll.x - deltaX) + "px";
        elementToDrag.style.top = (e.clientY + scroll.y - deltaY) + "px";

        console.log(2);

        if(e.stopPropagation)
            e.stopPropagation();
        else
            e.cancelBubble = true;
    }


    function upHandler(e){
        document.removeEventListener("mousemove", moveHandler, true);
        document.removeEventListener("mouseup", upHandler, true);
        
        console.log(3);
        
        if(e.stopPropagation)
            e.stopPropagation();
        else
            e.cancelBubble = true;
    }
}

所以我并没有明白书上的意思啊,究竟是我考虑的不周到,还是注册在两个阶段根本没有区别呢?


谈谈我的理解

首先这里翻译有误,

这是因为用户可能移动鼠标比其后的文档元素更快

这句话的原文如下:

because the user may move the mouse faster than the document element can follow it

其实在说这样的情况,鼠标移动的速度很快,而被拖动的元素跟不上鼠标的速度。

了解了这句话之后,就去分析,addEventListener方式其实对capture或者bubble都无影响,因为反正都是监听在document之上,不管鼠标多快,不管是不是超出目标元素的范围,mousemove事件都会发生,所以总会把目标元素移动到指定鼠标的位置

在我看来,这里的考虑是针对elementToDrag.attachEvent()这种方式的事件绑定,因为它将mousemove事件直接绑定在了目标元素上,那么如果鼠标移动太快,而元素没有跟上,那么mousemove事件就不会再目标元素身上发生,就触发不了处理函数。

但是其实使用capture阶段的,只是比bubble阶段调用处理函数敏捷(快)了一点,依旧会出现目标元素更不上的情况

【热门文章】
【热门文章】