You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ant-design-vue/components/trigger/Popup.vue

209 lines
5.5 KiB

7 years ago
<script>
7 years ago
import PropTypes from '../_util/vue-types'
7 years ago
import Align from '../align'
import PopupInner from './PopupInner'
import LazyRenderBox from './LazyRenderBox'
7 years ago
import { noop } from './utils'
7 years ago
export default {
props: {
visible: PropTypes.bool,
getClassNameFromAlign: PropTypes.func,
getRootDomNode: PropTypes.func,
align: PropTypes.any,
destroyPopupOnHide: PropTypes.bool,
prefixCls: PropTypes.string,
7 years ago
getContainer: PropTypes.func,
7 years ago
transitionName: PropTypes.string,
animation: PropTypes.any,
maskAnimation: PropTypes.string,
maskTransitionName: PropTypes.string,
mask: PropTypes.bool,
zIndex: PropTypes.number,
7 years ago
popupClassName: PropTypes.any,
7 years ago
},
7 years ago
data () {
return {
destroyPopup: false,
7 years ago
initAlign: false, // mounted之后再实例化align,即改变this.$el位置后实例化
7 years ago
}
},
7 years ago
mounted () {
this.rootNode = this.getPopupDomNode()
7 years ago
this._container = this.getContainer()
7 years ago
this._container.appendChild(this.$el)
this.$nextTick(() => {
7 years ago
this.initAlign = true
7 years ago
})
7 years ago
},
7 years ago
beforeDestroy () {
this.$el.remove()
},
7 years ago
watch: {
visible (val) {
if (val) {
this.destroyPopup = false
}
},
7 years ago
initAlign (val) {
if (val) {
this.$nextTick(() => {
this.$refs.alignInstance.forceAlign()
})
}
},
7 years ago
},
7 years ago
methods: {
onAlign (popupDomNode, align) {
const props = this.$props
const currentAlignClassName = props.getClassNameFromAlign(align)
if (this.currentAlignClassName !== currentAlignClassName) {
7 years ago
popupDomNode.className = popupDomNode.className.replace(this.currentAlignClassName, currentAlignClassName)
7 years ago
this.currentAlignClassName = currentAlignClassName
}
7 years ago
this.$listeners.align && this.$listeners.align(popupDomNode, align)
7 years ago
},
getPopupDomNode () {
7 years ago
return this.$refs.popupInstance ? this.$refs.popupInstance.$el : null
7 years ago
},
getTarget () {
return this.$props.getRootDomNode()
},
getMaskTransitionName () {
const props = this.$props
let transitionName = props.maskTransitionName
const animation = props.maskAnimation
if (!transitionName && animation) {
transitionName = `${props.prefixCls}-${animation}`
}
return transitionName
},
getTransitionName () {
const props = this.$props
let transitionName = props.transitionName
7 years ago
if (!transitionName && typeof props.animation === 'string') {
transitionName = `${props.animation}`
7 years ago
}
7 years ago
return transitionName
7 years ago
},
getClassName (currentAlignClassName) {
7 years ago
return `${this.$props.prefixCls} ${this.$props.popupClassName} ${currentAlignClassName}`
7 years ago
},
7 years ago
afterLeave (el) {
if (this.destroyPopupOnHide) {
this.destroyPopup = true
}
},
7 years ago
getPopupElement () {
7 years ago
const { $props: props, $slots, $listeners } = this
7 years ago
const { align, visible, prefixCls, animation } = props
7 years ago
const { mouseenter, mouseleave } = $listeners
7 years ago
this.currentAlignClassName = this.currentAlignClassName || props.getClassNameFromAlign(align)
const className = this.getClassName(this.currentAlignClassName)
7 years ago
// const hiddenClassName = `${prefixCls}-hidden`
7 years ago
if (!visible) {
this.currentAlignClassName = null
}
7 years ago
// visible = true
7 years ago
const popupInnerProps = {
props: {
prefixCls,
visible,
},
7 years ago
class: `${className}`,
7 years ago
on: {
7 years ago
mouseenter: mouseenter || noop,
mouseleave: mouseleave || noop,
7 years ago
},
ref: 'popupInstance',
style: { ...this.getZIndexStyle() },
}
7 years ago
const transitionProps = {
props: Object.assign({
appear: true,
}, typeof animation === 'object' ? animation : { name: this.getTransitionName() }),
}
7 years ago
return (<transition
7 years ago
{...transitionProps}
7 years ago
onAfterLeave={this.afterLeave}
7 years ago
>
<Align
7 years ago
v-show={visible}
7 years ago
target={this.getTarget}
key='popup'
ref='alignInstance'
monitorWindowResize
disabled={!visible}
align={align}
onAlign={this.onAlign}
>
<PopupInner
{...popupInnerProps}
>
{$slots.default}
</PopupInner>
</Align>
7 years ago
</transition>)
7 years ago
},
getZIndexStyle () {
const style = {}
const props = this.$props
if (props.zIndex !== undefined) {
style.zIndex = props.zIndex
}
return style
},
getMaskElement () {
const props = this.$props
let maskElement
if (props.mask) {
7 years ago
const maskTransition = this.getMaskTransitionName()
7 years ago
maskElement = (
<LazyRenderBox
7 years ago
v-show={props.visible}
7 years ago
style={this.getZIndexStyle()}
key='mask'
class={`${props.prefixCls}-mask`}
visible={props.visible}
/>
)
if (maskTransition) {
maskElement = (
7 years ago
<transition
7 years ago
appear
7 years ago
name={maskTransition}
7 years ago
>
{maskElement}
7 years ago
</transition>
7 years ago
)
}
}
return maskElement
},
},
render () {
7 years ago
const { destroyPopup, getMaskElement, getPopupElement, initAlign } = this
7 years ago
return (
7 years ago
<div style='position: absolute; top: 0px; left: 0px; width: 100%;'>
7 years ago
{initAlign ? (
getMaskElement(),
destroyPopup
? null : getPopupElement()
) : null }
7 years ago
</div>
)
},
}
</script>
7 years ago