ant-design-vue/components/trigger/Popup.vue

241 lines
6.4 KiB
Vue
Raw Normal View History

2017-12-22 10:43:28 +00:00
<script>
2017-12-25 10:08:36 +00:00
import PropTypes from '../_util/vue-types'
2017-12-22 10:43:28 +00:00
import Align from '../align'
import PopupInner from './PopupInner'
import LazyRenderBox from './LazyRenderBox'
2018-01-12 08:10:41 +00:00
import { noop } from './utils'
2018-02-04 03:08:04 +00:00
import animate from '../_util/css-animation'
2017-12-22 10:43:28 +00:00
export default {
props: {
visible: PropTypes.bool,
getClassNameFromAlign: PropTypes.func,
getRootDomNode: PropTypes.func,
align: PropTypes.any,
destroyPopupOnHide: PropTypes.bool,
prefixCls: PropTypes.string,
2017-12-25 10:08:36 +00:00
getContainer: PropTypes.func,
2017-12-26 11:04:28 +00:00
transitionName: PropTypes.string,
animation: PropTypes.any,
maskAnimation: PropTypes.string,
maskTransitionName: PropTypes.string,
mask: PropTypes.bool,
zIndex: PropTypes.number,
2018-01-03 10:30:12 +00:00
popupClassName: PropTypes.any,
2018-02-08 13:58:43 +00:00
popupStyle: PropTypes.object.def({}),
2017-12-22 10:43:28 +00:00
},
2017-12-27 08:13:26 +00:00
data () {
return {
destroyPopup: false,
2018-01-20 12:24:42 +00:00
initAlign: false, // mounted之后再实例化align,即改变this.$el位置后实例化,避免位置计算不正确
2017-12-27 08:13:26 +00:00
}
},
2017-12-22 10:43:28 +00:00
mounted () {
2018-02-02 09:42:05 +00:00
this.$nextTick(() => {
this.initAlign = true
})
2017-12-22 10:43:28 +00:00
},
2018-01-08 10:31:04 +00:00
beforeDestroy () {
this.$el.remove()
},
2018-02-03 11:48:03 +00:00
// beforeUpdate () {
// this.$nextTick(() => {
// const newContainer = this.getContainer()
// if (newContainer !== this._container) {
// this._container = newContainer
// this._container.appendChild(this.$el)
// this.$refs.alignInstance.forceAlign()
// }
// })
// },
2017-12-27 10:39:02 +00:00
watch: {
visible (val) {
if (val) {
this.destroyPopup = false
}
},
},
2017-12-22 10:43:28 +00:00
methods: {
onAlign (popupDomNode, align) {
const props = this.$props
const currentAlignClassName = props.getClassNameFromAlign(align)
2018-01-19 10:01:43 +00:00
popupDomNode.className = this.getClassName(currentAlignClassName)
2018-01-12 08:10:41 +00:00
this.$listeners.align && this.$listeners.align(popupDomNode, align)
2017-12-22 10:43:28 +00:00
},
getPopupDomNode () {
2017-12-26 11:04:28 +00:00
return this.$refs.popupInstance ? this.$refs.popupInstance.$el : null
2017-12-22 10:43:28 +00:00
},
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
2018-01-17 08:12:53 +00:00
const animation = props.animation
if (!transitionName) {
if (typeof animation === 'string') {
transitionName = `${animation}`
2018-02-07 15:03:47 +00:00
} else if (animation && animation.props && animation.props.name) {
2018-01-17 08:12:53 +00:00
transitionName = animation.props.name
}
2017-12-22 10:43:28 +00:00
}
2017-12-27 08:45:32 +00:00
return transitionName
2017-12-22 10:43:28 +00:00
},
getClassName (currentAlignClassName) {
2018-01-03 10:30:12 +00:00
return `${this.$props.prefixCls} ${this.$props.popupClassName} ${currentAlignClassName}`
2017-12-22 10:43:28 +00:00
},
getPopupElement () {
2018-01-16 02:42:16 +00:00
const { $props: props, $slots, $listeners, getTransitionName } = this
2018-02-08 13:58:43 +00:00
const { align, visible, prefixCls, animation, popupStyle } = props
2018-01-12 08:10:41 +00:00
const { mouseenter, mouseleave } = $listeners
2018-01-19 10:01:43 +00:00
const className = this.getClassName(props.getClassNameFromAlign(align))
2017-12-27 08:13:26 +00:00
// const hiddenClassName = `${prefixCls}-hidden`
2017-12-22 10:43:28 +00:00
const popupInnerProps = {
props: {
prefixCls,
visible,
2018-01-15 09:33:34 +00:00
// hiddenClassName,
2017-12-22 10:43:28 +00:00
},
2018-01-19 10:01:43 +00:00
class: className,
2017-12-22 10:43:28 +00:00
on: {
2018-01-12 08:10:41 +00:00
mouseenter: mouseenter || noop,
mouseleave: mouseleave || noop,
2017-12-22 10:43:28 +00:00
},
ref: 'popupInstance',
2018-02-08 13:58:43 +00:00
style: { ...this.getZIndexStyle(), ...popupStyle },
2017-12-22 10:43:28 +00:00
}
2018-02-09 10:42:19 +00:00
let transitionProps = {
2018-01-04 11:06:54 +00:00
props: Object.assign({
appear: true,
2018-01-15 09:33:34 +00:00
css: false,
}),
}
2018-01-16 02:42:16 +00:00
const transitionName = getTransitionName()
2018-02-09 10:42:19 +00:00
let useTransition = !!transitionName
2018-01-15 09:33:34 +00:00
const transitionEvent = {
beforeEnter: (el) => {
2018-01-19 04:14:07 +00:00
el.style.display = el.__vOriginalDisplay
2018-02-22 09:19:47 +00:00
// this.$refs.alignInstance.forceAlign()
2018-01-15 09:33:34 +00:00
},
enter: (el, done) => {
2018-02-22 09:19:47 +00:00
// align updated后执行动画
this.$nextTick(() => {
animate(el, `${transitionName}-enter`, done)
})
2018-01-15 09:33:34 +00:00
},
leave: (el, done) => {
2018-01-16 02:42:16 +00:00
animate(el, `${transitionName}-leave`, done)
2018-01-15 09:33:34 +00:00
},
afterLeave: (el) => {
if (this.destroyPopupOnHide) {
this.destroyPopup = true
}
},
}
if (typeof animation === 'object') {
2018-02-09 10:42:19 +00:00
useTransition = true
2018-01-17 08:12:53 +00:00
const { on = {}, props = {}} = animation
transitionProps.props = { ...transitionProps.props, ...props }
transitionProps.on = { ...transitionEvent, ...on, afterLeave: (el) => {
2018-01-15 09:33:34 +00:00
transitionEvent.afterLeave(el)
on.afterLeave && on.afterLeave(el)
} }
} else {
transitionProps.on = transitionEvent
2018-01-04 11:06:54 +00:00
}
2018-02-09 10:42:19 +00:00
if (!useTransition) {
transitionProps = {}
}
2017-12-25 10:08:36 +00:00
return (<transition
2018-01-04 11:06:54 +00:00
{...transitionProps}
2017-12-22 10:43:28 +00:00
>
<Align
2017-12-26 11:04:28 +00:00
v-show={visible}
2017-12-22 10:43:28 +00:00
target={this.getTarget}
key='popup'
ref='alignInstance'
monitorWindowResize
align={align}
onAlign={this.onAlign}
2018-02-22 09:19:47 +00:00
visible={visible}
2017-12-22 10:43:28 +00:00
>
<PopupInner
{...popupInnerProps}
>
{$slots.default}
</PopupInner>
</Align>
2017-12-25 10:08:36 +00:00
</transition>)
2017-12-22 10:43:28 +00:00
},
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) {
2017-12-27 08:45:32 +00:00
const maskTransition = this.getMaskTransitionName()
2017-12-22 10:43:28 +00:00
maskElement = (
<LazyRenderBox
2017-12-27 08:13:26 +00:00
v-show={props.visible}
2017-12-22 10:43:28 +00:00
style={this.getZIndexStyle()}
key='mask'
class={`${props.prefixCls}-mask`}
visible={props.visible}
/>
)
if (maskTransition) {
maskElement = (
2017-12-25 10:08:36 +00:00
<transition
2017-12-27 08:13:26 +00:00
appear
2017-12-25 10:08:36 +00:00
name={maskTransition}
2017-12-22 10:43:28 +00:00
>
{maskElement}
2017-12-25 10:08:36 +00:00
</transition>
2017-12-22 10:43:28 +00:00
)
}
}
return maskElement
},
},
render () {
2018-01-08 10:31:04 +00:00
const { destroyPopup, getMaskElement, getPopupElement, initAlign } = this
2017-12-22 10:43:28 +00:00
return (
2018-02-03 11:48:03 +00:00
<div>
2018-01-08 10:31:04 +00:00
{initAlign ? (
getMaskElement(),
destroyPopup
? null : getPopupElement()
) : null }
2017-12-22 10:43:28 +00:00
</div>
)
},
}
</script>
2017-12-26 11:04:28 +00:00