mirror of
https://gitee.com/element-plus/element-plus.git
synced 2024-12-14 17:31:02 +08:00
207 lines
4.6 KiB
TypeScript
207 lines
4.6 KiB
TypeScript
|
import {
|
||
|
nextTick,
|
||
|
reactive,
|
||
|
onBeforeMount,
|
||
|
onBeforeUnmount,
|
||
|
onMounted,
|
||
|
getCurrentInstance,
|
||
|
watch,
|
||
|
} from 'vue'
|
||
|
import PopupManager from '../popup-manager'
|
||
|
import getScrollBarWidth from '../scrollbar-width'
|
||
|
import { getStyle, addClass, removeClass, hasClass } from '../dom'
|
||
|
import isServer from '../isServer'
|
||
|
|
||
|
let idSeed = 1
|
||
|
|
||
|
let scrollBarWidth
|
||
|
|
||
|
export const usePopup1 = {
|
||
|
watch: {
|
||
|
visible(val) {
|
||
|
if (val) {
|
||
|
if (this._opening) return
|
||
|
if (!this.rendered) {
|
||
|
this.rendered = true
|
||
|
nextTick(() => {
|
||
|
this.open()
|
||
|
}).then(() => {
|
||
|
//
|
||
|
})
|
||
|
} else {
|
||
|
this.open()
|
||
|
}
|
||
|
} else {
|
||
|
this.close()
|
||
|
}
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
const usePopup = (props, doClose) => {
|
||
|
let _popupId
|
||
|
let _opening = false
|
||
|
let _closing = false
|
||
|
let vm
|
||
|
let _closeTimer = null
|
||
|
let _openTimer = null
|
||
|
const state = reactive<State>({
|
||
|
opened: false,
|
||
|
bodyPaddingRight: null,
|
||
|
computedBodyPaddingRight: 0,
|
||
|
withoutHiddenClass: true,
|
||
|
rendered: false,
|
||
|
visible: false,
|
||
|
})
|
||
|
|
||
|
onMounted(() => {
|
||
|
vm = getCurrentInstance()
|
||
|
})
|
||
|
|
||
|
onBeforeMount(() => {
|
||
|
_popupId = 'popup-' + idSeed++
|
||
|
PopupManager.register(_popupId, vm)
|
||
|
})
|
||
|
|
||
|
onBeforeUnmount(() => {
|
||
|
PopupManager.deregister(_popupId)
|
||
|
PopupManager.closeModal(_popupId)
|
||
|
restoreBodyStyle()
|
||
|
})
|
||
|
|
||
|
const doOpen = merProps => {
|
||
|
if (isServer) return
|
||
|
if (state.opened) return
|
||
|
|
||
|
_opening = true
|
||
|
|
||
|
const dom = vm.vnode.el
|
||
|
|
||
|
const modal = merProps.modal
|
||
|
|
||
|
const zIndex = merProps.zIndex
|
||
|
if (zIndex) {
|
||
|
PopupManager.zIndex = zIndex
|
||
|
}
|
||
|
|
||
|
if (modal) {
|
||
|
if (_closing) {
|
||
|
PopupManager.closeModal(_popupId)
|
||
|
_closing = false
|
||
|
}
|
||
|
PopupManager.openModal(_popupId, PopupManager.nextZIndex(), props.modalAppendToBody ? undefined : dom, merProps.modalClass, merProps.modalFade)
|
||
|
if (merProps.lockScroll) {
|
||
|
state.withoutHiddenClass = !hasClass(document.body, 'el-popup-parent--hidden')
|
||
|
if (state.withoutHiddenClass) {
|
||
|
state.bodyPaddingRight = document.body.style.paddingRight
|
||
|
state.computedBodyPaddingRight = parseInt(getStyle(document.body, 'paddingRight'), 10)
|
||
|
}
|
||
|
scrollBarWidth = getScrollBarWidth()
|
||
|
const bodyHasOverflow = document.documentElement.clientHeight < document.body.scrollHeight
|
||
|
const bodyOverflowY = getStyle(document.body, 'overflowY')
|
||
|
if (scrollBarWidth > 0 && (bodyHasOverflow || bodyOverflowY === 'scroll') && state.withoutHiddenClass) {
|
||
|
document.body.style.paddingRight = state.computedBodyPaddingRight + scrollBarWidth + 'px'
|
||
|
}
|
||
|
addClass(document.body, 'el-popup-parent--hidden')
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (getComputedStyle(dom).position === 'static') {
|
||
|
dom.style.position = 'absolute'
|
||
|
}
|
||
|
|
||
|
dom.style.zIndex = PopupManager.nextZIndex()
|
||
|
state.opened = true
|
||
|
|
||
|
doAfterOpen()
|
||
|
}
|
||
|
|
||
|
const open = function (options?) {
|
||
|
if (!state.rendered) {
|
||
|
state.rendered = true
|
||
|
}
|
||
|
const _props = Object.assign({}, props || vm.proxy, options)
|
||
|
|
||
|
if (_closeTimer) {
|
||
|
clearTimeout(_closeTimer)
|
||
|
_closeTimer = null
|
||
|
}
|
||
|
clearTimeout(_openTimer)
|
||
|
|
||
|
const openDelay = Number(_props.openDelay)
|
||
|
if (openDelay > 0) {
|
||
|
_openTimer = setTimeout(() => {
|
||
|
_openTimer = null
|
||
|
doOpen(_props)
|
||
|
}, openDelay)
|
||
|
} else {
|
||
|
doOpen(_props)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const close = () => {
|
||
|
if (_openTimer !== null) {
|
||
|
clearTimeout(_openTimer)
|
||
|
_openTimer = null
|
||
|
}
|
||
|
clearTimeout(_closeTimer)
|
||
|
|
||
|
const closeDelay = Number(props.closeDelay)
|
||
|
|
||
|
if (closeDelay > 0) {
|
||
|
_closeTimer = setTimeout(() => {
|
||
|
_closeTimer = null
|
||
|
doClose()
|
||
|
}, closeDelay)
|
||
|
} else {
|
||
|
doClose()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const doAfterOpen = () => {
|
||
|
_opening = false
|
||
|
}
|
||
|
|
||
|
const restoreBodyStyle = () => {
|
||
|
if (props.modal && state.withoutHiddenClass) {
|
||
|
document.body.style.paddingRight = state.bodyPaddingRight
|
||
|
removeClass(document.body, 'el-popup-parent--hidden')
|
||
|
}
|
||
|
state.withoutHiddenClass = true
|
||
|
}
|
||
|
|
||
|
const doAfterClose = () => {
|
||
|
PopupManager.closeModal(_popupId)
|
||
|
_closing = false
|
||
|
}
|
||
|
|
||
|
const updateClosingFlag = value => {
|
||
|
_closing = value
|
||
|
}
|
||
|
|
||
|
watch(() => state.visible, async val => {
|
||
|
if (val) {
|
||
|
if (_opening) return
|
||
|
if (!state.rendered) {
|
||
|
state.rendered = true
|
||
|
await nextTick()
|
||
|
open()
|
||
|
} else {
|
||
|
open()
|
||
|
}
|
||
|
} else {
|
||
|
close()
|
||
|
}
|
||
|
})
|
||
|
|
||
|
return {
|
||
|
state,
|
||
|
close,
|
||
|
doAfterClose,
|
||
|
updateClosingFlag,
|
||
|
restoreBodyStyle,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export default usePopup
|