代码链接
这是来自《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()
这个就跟事件本身是谁有关了,然而我不知道这会产生什么不良的影响?
不知道以上的理解有没有问题,求证。
“DOM2级事件”规定的事件流包括三个阶段:
- 事件捕获
- 处于目标阶段
- 事件冒泡
首先发送事件捕获, 然后实际目标接受到事件,最后是事件冒泡。
addEventListener()
和removeEventListener()
的第三个参数是布尔值,true
表示在捕获阶段调用事件处理程序,false
则是在冒泡阶段调用事件处理程序。p.s.《JavaScript高级程序设计》第13章详细介绍了事件。