mirror of
https://gitee.com/element-plus/element-plus.git
synced 2024-12-15 09:50:58 +08:00
85 lines
2.4 KiB
Vue
85 lines
2.4 KiB
Vue
<script lang="ts">
|
|
import { createVNode, defineComponent, renderSlot, h } from 'vue'
|
|
import { PatchFlags } from '@element-plus/utils/vnode'
|
|
|
|
export default defineComponent({
|
|
name: 'ElOverlay',
|
|
props: {
|
|
mask: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
overlayClass: {
|
|
type: [String, Array, Object],
|
|
},
|
|
zIndex: {
|
|
type: Number,
|
|
},
|
|
},
|
|
emits: ['click'],
|
|
setup(props, { slots, emit }) {
|
|
let mousedownTarget = false
|
|
let mouseupTarget = false
|
|
// refer to this https://javascript.info/mouse-events-basics
|
|
// events fired in the order: mousedown -> mouseup -> click
|
|
// we need to set the mousedown handle to false after click
|
|
// fired.
|
|
const onMaskClick = (e: MouseEvent) => {
|
|
// due to these two value were set only when props.mask is true
|
|
// so there is no need to do any extra judgment here.
|
|
// if and only if
|
|
if (mousedownTarget && mouseupTarget) {
|
|
emit('click', e)
|
|
}
|
|
mousedownTarget = mouseupTarget = false
|
|
}
|
|
|
|
// init here
|
|
return () => {
|
|
// when the vnode meets the same structure but with different change trigger
|
|
// it will not automatically update, thus we simply use h function to manage updating
|
|
return props.mask
|
|
? createVNode(
|
|
'div',
|
|
{
|
|
class: ['el-overlay', props.overlayClass],
|
|
style: {
|
|
zIndex: props.zIndex,
|
|
},
|
|
onClick: onMaskClick,
|
|
onMousedown: (e: MouseEvent) => {
|
|
// marking current mousedown target.
|
|
if (props.mask) {
|
|
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'],
|
|
)
|
|
: h(
|
|
'div',
|
|
{
|
|
class: props.overlayClass,
|
|
style: {
|
|
zIndex: props.zIndex,
|
|
position: 'fixed',
|
|
top: '0px',
|
|
right: '0px',
|
|
bottom: '0px',
|
|
left: '0px',
|
|
},
|
|
},
|
|
[renderSlot(slots, 'default')],
|
|
)
|
|
}
|
|
},
|
|
})
|
|
</script>
|