事件捕获问题?

代码链接
这是来自《javascript权威指南》17-2的代码,不过我把以下的第三个参数全部修改成了false(原文是true)。

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

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

看似并没有出现问题。

事件传播的三个阶段的原理我已经了解了,我并不是不知道这个,我是不知道在这个case把true改为false会有什么区别?

我阐述一下我的理解,拿moveHandler来说:
当鼠标移动时,先进行事件捕获,从window开始捕获,然而并没有相应的capturing event handler,然后把事件传到下一层document,由于document注册了capturing event handler,所以调用了该hanler,随后执行到e.stopPropagation时停止事件的后续传播。

如果换成false的话:首先跳过capture阶段(因为没有注册任何相关的capturing event handler),然后事件传递到target,但是target上没有注册跟mousemove有关的handler,因此跳过此阶段,进行bubble阶段,于是事件传呀传呀传到了document,被其注册的bubble阶段的handler所接收到,然后调用该handler,执行相应代码。

这两种我觉得从结果上来讲没有任何区别,如果非要说区别的话,我觉得只是用true速度快一些,因为在捕获阶段就停止了事件的后续传播。

但是原文中写到:

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

的确,某些mousemove事件会发生在原始目标元素之外,这会导致事件的target未必一直是我们所拖动的那个元素,但这样会产生任何问题吗?我们用到的与事件对象相关的代码只有这些:

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

也就是只用到了事件对象的坐标属性,与事件本身是谁没有关系。
不过还有一句我比较困惑:

if (e.stopPropagation) e.stopPropagation()

这个就跟事件本身是谁有关了,然而我不知道这会产生什么不良的影响?

不知道以上的理解有没有问题,求证。

阅读 3.1k
2 个回答

“DOM2级事件”规定的事件流包括三个阶段:
- 事件捕获
- 处于目标阶段
- 事件冒泡

首先发送事件捕获, 然后实际目标接受到事件,最后是事件冒泡。

“DOM2级事件”规范明确要求捕获阶段不涉及事件目标,但现代浏览器都会在捕获阶段触发事件目标对象上的事件。所以有两个机会在目标对象上操作事件。

addEventListener()removeEventListener()的第三个参数是布尔值,true表示在捕获阶段调用事件处理程序,false则是在冒泡阶段调用事件处理程序。

p.s.《JavaScript高级程序设计》第13章详细介绍了事件。

如果将 useCapture 设置为 true,则侦听器只在捕获阶段处理事件,而不在目标或冒泡阶段处理事件。 如果useCapture 为 false,则侦听器只在目标或冒泡阶段处理事件。 要在所有三个阶段都侦听事件,请调用两次 addEventListener,一次将 useCapture 设置为 true,第二次再将useCapture 设置为 false。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题