此类事件不仅可能来自于鼠标、触控板,还可能来自于对此类操作进行了模拟以实现兼容性的其他设备,例如手机和平板电脑
mousedown、mouseup:在元素上点击/释放鼠标按键click:在元素上单击鼠标左键
mousedown,当鼠标左键被释放时,会依次触发 mouseup 和 clickdblclick:在元素上短时间内双击鼠标左键
mousedown -> mouseup -> click 乘 2 后,触发 dblclickcontextmenu:在元素上鼠标右键被按下时触发
mousedown 和 contextmenu,当鼠标右键被释放时触发 mouseupevent.button:获得按下的按键
0:左键(主要按键)1:中键(辅助按键)2:右键(次要按键)3:X1 键(后退按键)4:X2 键(前进按键)event.which:获得按下的按键,过时的
1:左键2:中键3:右键event.buttons:以整数的形式存储着当前所有按下的鼠标按键,每个按键一个比特位
在 mousedown 和 mouseup 中可能需要。因为 click 和 dblclick 是左键;contextmenu 是右键
[[013.键盘事件#组合键|键盘组合键]]
双击鼠标会有副作用,在某些界面中可能会出现干扰:它会选择文本
比如,双击下面的文本,除了我们的处理程序外,还会选择文本:
<span ondblclick="alert('dblclick')">Double-click me</span>
如果按下鼠标左键,并在不松开的情况下移动鼠标,这也常常会造成不必要的选择
有多种防止选择的方法:选择(Selection)和范围(Range)
在这种情况下,最合理的方式是防止浏览器对 mousedown 进行操作。这样能够阻止刚刚提到的两种选择:
Before...
<b ondblclick="alert('Click!')" onmousedown="return false">
Double-click me
</b>
...After
现在,在双击时,粗体元素不会被选中,并且在粗体元素上按下鼠标左键也不会开始选择
请注意:其中的文本仍然是可选择的。但是,选择不应该开始于该文本自身,而应该在该文本之前或之后开始。通常,这对用户来说挺好的
复制事件:copy,阻止其默认行为即可无法复制:
<div oncopy="alert('Copying forbidden!');return false">
Dear user,
The copying is forbidden for you.
If you know JS or HTML, then you can get everything from the page source though.
</div>
当然,用户可以访问页面的 HTML 源码,并且可以从那里获取内容,但并不是每个人都知道如何做到这一点
mousemove:鼠标在元素上的每个移动都会触发此事件mouseover:鼠标指针移入(进入)元素时
event.target:当前移入的元素event.relatedTarget:鼠标来自的那个元素relatedTarget 移入到 targetmouseout:鼠标指针移出(离开)元素时
event.target:鼠标移出的元素event.relatedTarget:鼠标移动到的元素target 移出,到了 relatedTargetmouseenter/mouseleave:类似于 mouseover/mouseout
event.relatedTargetrelatedTarget 可以为 null:意味着鼠标不是来自另一个元素,而是来自窗口之外。或者它离开了窗口
mouseover/mouseout 与 mouseenter/mouseleave 的区别:
mouseover/mouseout 冒泡mouseenter/mouseleave 不冒泡mouseover/mouseout 当鼠标指针从当前元素移动到其后代时会触发当前元素的 mouseoutmouseenter/mouseleave 元素内部与后代之间的转换不会产生影响鼠标指针从 #parent 移到 #child,在 #parent 上会触发 mouseout:
![[Pasted image 20240430110443.png|300]]
解释:鼠标指针位于单个元素上 —— 嵌套最多的那个元素(z-index 最大的那个),如果它转到另一个元素(甚至是一个后代),那么它将离开前一个元素
注意另一个重要的细节:后代的 mouseover 事件会冒泡。因此,如果 #parent 具有 mouseover 处理程序,它将被触发:
![[Pasted image 20240430110924.png|300]]
<div id="parent" onmouseover="mouselog(event)" onmouseout="mouselog(event)">parent
<div id="child">child</div>
</div>
如果将鼠标从 #parent 移动到 #child,那么在 #parent 上有两个事件:
mouseout [target: parent](离开 parent),然后mouseover [target: child](来到 child,冒泡)而 mouseenter/mouseleave 不同:鼠标指针在当前元素和其后代上都认为是 enter
当鼠标移动时,就会触发 mousemove 事件,但这并不意味着每个像素都会导致一个事件
而是浏览器会有一个时间间隔检查鼠标的位置,如果发现了变化,就会触发事件
即:靠时间间隔判断鼠标移动,而不是像素点。这对性能很有好处
这意味着,如果访问者非常快地移动鼠标,那么某些 DOM 元素的事件可能被跳过:
![[Pasted image 20240430105112.png]]
如果鼠标从上图所示的 #FROM 快速移动到 #TO 元素,则中间的 <div>(或其中的一些)元素可能会被跳过。mouseout 事件可能会在 #FROM 上被触发,然后立即在 #TO 上触发 mouseover
应该记住,鼠标指针并不会“访问”所有元素,它可以“跳过”一些元素
注意:虽然可能“跳过”,但如果 mouseover 或 mouseenter 被触发了,则离开时必定有 mouseout 或 mouseleave
使用鼠标事件来实现拖放(Drag’n’Drop)效果:
mousedown 上 —— 根据需要准备要移动的元素(也许创建一个它的副本,向其中添加一个类或其他东西)mousemove 上,通过更改 position: absolute 情况下的 left/top 来移动它mouseup 上 —— 执行与完成的拖放相关的所有行为注意:
ondragstartmousemove 应该绑定到 document,因为在快速移动鼠标时,鼠标指针可能会跳转至文档中间的某个位置(甚至跳转至窗口外)mousemove 是不可行的,因为“draggable”才是 z-index 更大的,底层“droppable”的 mousemove 事件并不会被触发mousemove,拿“droppable”:
draggable.hidden = trueconst droppable = document.elementFromPoint(event.clientX, event.clientY)draggable.hidden = false在现代 HTML 标准中有一个 关于拖放的部分,详见 [[012.拖拽事件|拖拽事件]]
原生拖放事件会有很多先进的特性以供开发者使用,但也有其局限性。例如,无法阻止从特定区域的拖动,无法将拖动变成“水平”或“竖直”的。还有很多其他使用它们无法完成的拖放任务。并且,移动设备对此类事件的支持非常有限
所以具体选用什么方案还是要看实际的需求
所有的鼠标事件都提供了 [[007.几何信息#两种坐标系|两种形式的坐标]]:
event.clientX 和 event.clientYevent.pageX 和 event.pageY