2017-12-22 18:43:28 +08:00
|
|
|
<script>
|
2017-12-25 18:08:36 +08:00
|
|
|
import PropTypes from '../_util/vue-types'
|
2017-12-22 18:43:28 +08:00
|
|
|
import Align from '../align'
|
|
|
|
import PopupInner from './PopupInner'
|
|
|
|
import LazyRenderBox from './LazyRenderBox'
|
2018-01-12 16:10:41 +08:00
|
|
|
import { noop } from './utils'
|
2018-01-15 17:33:34 +08:00
|
|
|
import animate from 'css-animation'
|
2017-12-22 18:43:28 +08: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 18:08:36 +08:00
|
|
|
getContainer: PropTypes.func,
|
2017-12-26 19:04:28 +08:00
|
|
|
transitionName: PropTypes.string,
|
|
|
|
animation: PropTypes.any,
|
|
|
|
maskAnimation: PropTypes.string,
|
|
|
|
maskTransitionName: PropTypes.string,
|
|
|
|
mask: PropTypes.bool,
|
|
|
|
zIndex: PropTypes.number,
|
2018-01-03 18:30:12 +08:00
|
|
|
popupClassName: PropTypes.any,
|
2017-12-22 18:43:28 +08:00
|
|
|
},
|
2017-12-27 16:13:26 +08:00
|
|
|
data () {
|
|
|
|
return {
|
2018-01-15 17:33:34 +08:00
|
|
|
aligned: false,
|
2017-12-27 16:13:26 +08:00
|
|
|
destroyPopup: false,
|
2018-01-08 18:31:04 +08:00
|
|
|
initAlign: false, // mounted之后再实例化align,即改变this.$el位置后实例化
|
2017-12-27 16:13:26 +08:00
|
|
|
}
|
|
|
|
},
|
2017-12-22 18:43:28 +08:00
|
|
|
mounted () {
|
|
|
|
this.rootNode = this.getPopupDomNode()
|
2017-12-25 18:08:36 +08:00
|
|
|
this._container = this.getContainer()
|
2017-12-27 16:13:26 +08:00
|
|
|
this._container.appendChild(this.$el)
|
|
|
|
this.$nextTick(() => {
|
2018-01-08 18:31:04 +08:00
|
|
|
this.initAlign = true
|
2017-12-27 16:13:26 +08:00
|
|
|
})
|
2017-12-22 18:43:28 +08:00
|
|
|
},
|
2018-01-08 18:31:04 +08:00
|
|
|
beforeDestroy () {
|
|
|
|
this.$el.remove()
|
|
|
|
},
|
2017-12-27 18:39:02 +08:00
|
|
|
watch: {
|
|
|
|
visible (val) {
|
|
|
|
if (val) {
|
|
|
|
this.destroyPopup = false
|
|
|
|
}
|
|
|
|
},
|
2018-01-08 18:31:04 +08:00
|
|
|
initAlign (val) {
|
|
|
|
if (val) {
|
|
|
|
this.$nextTick(() => {
|
2018-01-15 17:33:34 +08:00
|
|
|
// console.log(this.$refs.alignInstance.$el)
|
|
|
|
// this.$refs.alignInstance.forceAlign()
|
2018-01-08 18:31:04 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
},
|
2017-12-27 18:39:02 +08:00
|
|
|
},
|
2017-12-22 18:43:28 +08:00
|
|
|
methods: {
|
|
|
|
onAlign (popupDomNode, align) {
|
|
|
|
const props = this.$props
|
|
|
|
const currentAlignClassName = props.getClassNameFromAlign(align)
|
|
|
|
if (this.currentAlignClassName !== currentAlignClassName) {
|
2018-01-11 18:53:51 +08:00
|
|
|
popupDomNode.className = popupDomNode.className.replace(this.currentAlignClassName, currentAlignClassName)
|
2017-12-22 18:43:28 +08:00
|
|
|
this.currentAlignClassName = currentAlignClassName
|
|
|
|
}
|
2018-01-12 16:10:41 +08:00
|
|
|
this.$listeners.align && this.$listeners.align(popupDomNode, align)
|
2017-12-22 18:43:28 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
getPopupDomNode () {
|
2017-12-26 19:04:28 +08:00
|
|
|
return this.$refs.popupInstance ? this.$refs.popupInstance.$el : null
|
2017-12-22 18:43:28 +08: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-04 19:06:54 +08:00
|
|
|
if (!transitionName && typeof props.animation === 'string') {
|
|
|
|
transitionName = `${props.animation}`
|
2017-12-22 18:43:28 +08:00
|
|
|
}
|
2017-12-27 16:45:32 +08:00
|
|
|
return transitionName
|
2017-12-22 18:43:28 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
getClassName (currentAlignClassName) {
|
2018-01-03 18:30:12 +08:00
|
|
|
return `${this.$props.prefixCls} ${this.$props.popupClassName} ${currentAlignClassName}`
|
2017-12-22 18:43:28 +08:00
|
|
|
},
|
|
|
|
getPopupElement () {
|
2018-01-12 16:10:41 +08:00
|
|
|
const { $props: props, $slots, $listeners } = this
|
2018-01-04 19:06:54 +08:00
|
|
|
const { align, visible, prefixCls, animation } = props
|
2018-01-12 16:10:41 +08:00
|
|
|
const { mouseenter, mouseleave } = $listeners
|
2018-01-11 18:53:51 +08:00
|
|
|
this.currentAlignClassName = this.currentAlignClassName || props.getClassNameFromAlign(align)
|
|
|
|
const className = this.getClassName(this.currentAlignClassName)
|
2017-12-27 16:13:26 +08:00
|
|
|
// const hiddenClassName = `${prefixCls}-hidden`
|
2017-12-22 18:43:28 +08:00
|
|
|
if (!visible) {
|
|
|
|
this.currentAlignClassName = null
|
|
|
|
}
|
2017-12-25 18:08:36 +08:00
|
|
|
// visible = true
|
2017-12-22 18:43:28 +08:00
|
|
|
const popupInnerProps = {
|
|
|
|
props: {
|
|
|
|
prefixCls,
|
|
|
|
visible,
|
2018-01-15 17:33:34 +08:00
|
|
|
// hiddenClassName,
|
2017-12-22 18:43:28 +08:00
|
|
|
},
|
2018-01-03 18:30:12 +08:00
|
|
|
class: `${className}`,
|
2017-12-22 18:43:28 +08:00
|
|
|
on: {
|
2018-01-12 16:10:41 +08:00
|
|
|
mouseenter: mouseenter || noop,
|
|
|
|
mouseleave: mouseleave || noop,
|
2017-12-22 18:43:28 +08:00
|
|
|
},
|
|
|
|
ref: 'popupInstance',
|
|
|
|
style: { ...this.getZIndexStyle() },
|
|
|
|
}
|
2018-01-04 19:06:54 +08:00
|
|
|
const transitionProps = {
|
|
|
|
props: Object.assign({
|
|
|
|
appear: true,
|
2018-01-15 17:33:34 +08:00
|
|
|
css: false,
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
let opacity = '1'
|
|
|
|
const transitionEvent = {
|
|
|
|
beforeEnter: (el) => {
|
|
|
|
opacity = el.style.opacity
|
|
|
|
el.style.opacity = '0'
|
|
|
|
!this.aligned && this.$refs.alignInstance.forceAlign()
|
|
|
|
this.aligned = true
|
|
|
|
},
|
|
|
|
enter: (el, done) => {
|
|
|
|
el.style.opacity = opacity
|
|
|
|
animate(el, 'zoom-big-enter', done)
|
|
|
|
},
|
|
|
|
leave: (el, done) => {
|
|
|
|
animate(el, 'zoom-big-leave', done)
|
|
|
|
},
|
|
|
|
afterLeave: (el) => {
|
|
|
|
if (this.destroyPopupOnHide) {
|
|
|
|
this.destroyPopup = true
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof animation === 'object') {
|
|
|
|
const { on = {}, ...otherProps } = animation
|
|
|
|
transitionProps.props = { ...transitionProps.props, ...otherProps }
|
|
|
|
transitionProps.on = { ...on, afterLeave: (el) => {
|
|
|
|
transitionEvent.afterLeave(el)
|
|
|
|
on.afterLeave && on.afterLeave(el)
|
|
|
|
} }
|
|
|
|
} else {
|
|
|
|
transitionProps.on = transitionEvent
|
2018-01-04 19:06:54 +08:00
|
|
|
}
|
2017-12-25 18:08:36 +08:00
|
|
|
return (<transition
|
2018-01-04 19:06:54 +08:00
|
|
|
{...transitionProps}
|
2017-12-22 18:43:28 +08:00
|
|
|
>
|
|
|
|
<Align
|
2017-12-26 19:04:28 +08:00
|
|
|
v-show={visible}
|
2017-12-22 18:43:28 +08:00
|
|
|
target={this.getTarget}
|
|
|
|
key='popup'
|
|
|
|
ref='alignInstance'
|
|
|
|
monitorWindowResize
|
|
|
|
disabled={!visible}
|
|
|
|
align={align}
|
|
|
|
onAlign={this.onAlign}
|
|
|
|
>
|
|
|
|
<PopupInner
|
|
|
|
{...popupInnerProps}
|
|
|
|
>
|
|
|
|
{$slots.default}
|
|
|
|
</PopupInner>
|
|
|
|
</Align>
|
2017-12-25 18:08:36 +08:00
|
|
|
</transition>)
|
2017-12-22 18:43:28 +08: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 16:45:32 +08:00
|
|
|
const maskTransition = this.getMaskTransitionName()
|
2017-12-22 18:43:28 +08:00
|
|
|
maskElement = (
|
|
|
|
<LazyRenderBox
|
2017-12-27 16:13:26 +08:00
|
|
|
v-show={props.visible}
|
2017-12-22 18:43:28 +08:00
|
|
|
style={this.getZIndexStyle()}
|
|
|
|
key='mask'
|
|
|
|
class={`${props.prefixCls}-mask`}
|
|
|
|
visible={props.visible}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
if (maskTransition) {
|
|
|
|
maskElement = (
|
2017-12-25 18:08:36 +08:00
|
|
|
<transition
|
2017-12-27 16:13:26 +08:00
|
|
|
appear
|
2017-12-25 18:08:36 +08:00
|
|
|
name={maskTransition}
|
2017-12-22 18:43:28 +08:00
|
|
|
>
|
|
|
|
{maskElement}
|
2017-12-25 18:08:36 +08:00
|
|
|
</transition>
|
2017-12-22 18:43:28 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return maskElement
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
render () {
|
2018-01-08 18:31:04 +08:00
|
|
|
const { destroyPopup, getMaskElement, getPopupElement, initAlign } = this
|
2017-12-22 18:43:28 +08:00
|
|
|
return (
|
2017-12-27 16:13:26 +08:00
|
|
|
<div style='position: absolute; top: 0px; left: 0px; width: 100%;'>
|
2018-01-08 18:31:04 +08:00
|
|
|
{initAlign ? (
|
|
|
|
getMaskElement(),
|
|
|
|
destroyPopup
|
|
|
|
? null : getPopupElement()
|
|
|
|
) : null }
|
|
|
|
|
2017-12-22 18:43:28 +08:00
|
|
|
</div>
|
|
|
|
)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
</script>
|
2017-12-26 19:04:28 +08:00
|
|
|
|