本文主要科普 mouseevent 的规范:
Each implementation will determine the appropriate hysteresis tolerance, but in general SHOULD fireclick
anddblclick
events when the event target of the associatedmousedown
andmouseup
events is the same element with nomouseout
ormouseleave
events intervening, and SHOULD fireclick
anddblclick
events on the nearest common inclusive ancestor when the associatedmousedown
andmouseup
event targets are different.
重点关注最后一句:当 mousedown
事件对象是 A, mouseup
的事件对象是 B, click
事件会在 A 和 B 共同的祖先节点触发。
先来看看一个 issue:鼠标在 Dialog
内部按下,滑动到 Dialog
外部时松开,Dialog 会关闭。
[Bug Report] 【el-dialog】close bug · Issue #15000 · ElemeFE/element
来看一下 Dialog
的代码,关闭 Dialog
的行为是在 handleWrapperClick
这个方法里面做的,绑定这个事件的时候发生
<div class="el-dialog__wrapper" v-show="visible" @click.self="handleWrapperClick">
<script>
export default {
methods: {
handleWrapperClick() {
if (!this.closeOnClickModal) return;
this.handleClose();
}
}
}
</script>
组件中使用了 vue
的事件修饰符 .self
,目的不希望点击事件在 <div class"el-dialog__wrapper">
节点的子节点触发的时候也关闭弹出框,如下图所示,点击弹窗内容的时候没有触发 handleWrapperClick
, 点击遮罩层的时候触发了 handleWrapperClick
事件关闭了弹窗 。
这个写法对于常用操作是没有问题的,但是如果鼠标在 Dialog
内部按下,滑动到 Dialog
外部时松开,会触发 handleWrapperClick
方法。 原因是:mousedown
事件对象是 A( Dialog
内部的节点), mouseup
的事件对象是B(遮罩层),click
事件会在 A 和 B 共同的祖先节点触发, 他们共同的节点是 B。
参考:
https://www.w3.org/TR/uievents/#events-mouseevent-event-order