一、组件介绍
el-overlay是element-plus内部使用的组件,官方文档没有给出此组件的相关描述。
该组件用于弹出一个覆盖层,被用于el-dialog和el-messagebox等组件中。
二、源码分析
export default defineComponent({
name: 'ElOverlay',
props: {
// 是否展示掩盖层
mask: {
type: Boolean,
default: true,
},
overlayClass: {
type: [String, Array, Object],
},
// 指定覆盖层的Index
zIndex: {
type: Number,
},
},
emits: ['click'],
setup(props, { slots, emit }) {
// 标识符,当鼠标事件在弹出的mask上触发时置为true
let mousedownTarget = false
let mouseupTarget = false
// 点击事件的触发顺序: mousedown -> mouseup -> click
// mask点击事件
const onMaskClick = (e: MouseEvent) => {
// 当mousedown及mouseup都是在mask元素上触发时,向外抛出click事件
// 是为了保证点击的行为是在Mask元素上触发的
//(为什么不直接在这里判断 e.target === e.currentTarget呢?)
if (mousedownTarget && mouseupTarget) {
emit('click', e)
}
// 重置标识符状态
mousedownTarget = mouseupTarget = false
}
// init here
return () => {
return props.mask
? createVNode(
// 展示mask时
'div',
{
class: ['el-overlay', props.overlayClass],
style: {
zIndex: props.zIndex,
},
// 绑定点击事件
onClick: onMaskClick,
onMousedown: (e: MouseEvent) => {
// props.mask的判断似乎可以去掉,上面已经判断过了
if (props.mask) {
// e.currentTarget指的是绑定该事件的元素
// 当事件触发对象是当前元素时,标识符置为true
mousedownTarget = e.target === e.currentTarget
}
},
onMouseup: (e: MouseEvent) => {
if (props.mask) {
// 同上
mouseupTarget = e.target === e.currentTarget
}
},
},
[renderSlot(slots, 'default')],
PatchFlags.STYLE | PatchFlags.CLASS | PatchFlags.PROPS,
['onClick', 'onMouseup', 'onMousedown'],
)
// 不展示mask
: h(
'div',
{
class: props.overlayClass,
style: {
zIndex: props.zIndex,
position: 'fixed',
top: '0px',
right: '0px',
bottom: '0px',
left: '0px',
},
},
[renderSlot(slots, 'default')],
)
}
},
})
三、总结
- 通过
mask属性控制是否展示一个mask层; event.currentTarget表示的是事件绑定的元素,可以使用event.target === event.currentTarget判断事件是否是由注册该事件响应函数的元素触发;- 鼠标点击的事件响应顺序是:
mouseDown -> mouseUp-> click; - 这里为啥不在click事件中判断
event.target === event.currentTarget呢,而是通过mouseDown和mouseUp事件中设置标志位来做??