158 lines
4.3 KiB
Vue
158 lines
4.3 KiB
Vue
|
<script>
|
||
|
import PropTypes from '../../_util/vue-types'
|
||
|
import Trigger from '../../trigger'
|
||
|
import placements from './placements'
|
||
|
import { hasProp } from '../../_util/props-util'
|
||
|
import BaseMixin from '../../_util/BaseMixin'
|
||
|
import { cloneElement, getEvents } from '../../_util/vnode'
|
||
|
|
||
|
export default {
|
||
|
mixins: [BaseMixin],
|
||
|
props: {
|
||
|
minOverlayWidthMatchTrigger: PropTypes.bool.def(true),
|
||
|
prefixCls: PropTypes.string.def('rc-dropdown'),
|
||
|
transitionName: PropTypes.string,
|
||
|
overlayClassName: PropTypes.string.def(''),
|
||
|
animation: PropTypes.any,
|
||
|
align: PropTypes.object,
|
||
|
overlayStyle: PropTypes.object.def({}),
|
||
|
placement: PropTypes.string.def('bottomLeft'),
|
||
|
trigger: PropTypes.array.def(['hover']),
|
||
|
showAction: PropTypes.array.def([]),
|
||
|
hideAction: PropTypes.array.def([]),
|
||
|
getPopupContainer: PropTypes.func,
|
||
|
visible: PropTypes.bool,
|
||
|
defaultVisible: PropTypes.bool.def(false),
|
||
|
mouseEnterDelay: PropTypes.number.def(0.15),
|
||
|
mouseLeaveDelay: PropTypes.number.def(0.1),
|
||
|
},
|
||
|
data () {
|
||
|
let sVisible = this.defaultVisible
|
||
|
if (hasProp(this, 'visible')) {
|
||
|
sVisible = this.visible
|
||
|
}
|
||
|
return {
|
||
|
sVisible,
|
||
|
}
|
||
|
},
|
||
|
watch: {
|
||
|
visible (val) {
|
||
|
if (val !== undefined) {
|
||
|
this.setState({
|
||
|
sVisible: val,
|
||
|
})
|
||
|
}
|
||
|
},
|
||
|
},
|
||
|
methods: {
|
||
|
onClick (e) {
|
||
|
// do no call onVisibleChange, if you need click to hide, use onClick and control visible
|
||
|
if (!hasProp(this, 'visible')) {
|
||
|
this.setState({
|
||
|
sVisible: false,
|
||
|
})
|
||
|
}
|
||
|
this.$emit('overlayClick', e)
|
||
|
if (this.childOriginEvents.click) {
|
||
|
this.childOriginEvents.click(e)
|
||
|
}
|
||
|
},
|
||
|
|
||
|
onVisibleChange (visible) {
|
||
|
if (!hasProp(this, 'visible')) {
|
||
|
this.setState({
|
||
|
sVisible: visible,
|
||
|
})
|
||
|
}
|
||
|
this.__emit('visibleChange', visible)
|
||
|
},
|
||
|
|
||
|
getMenuElement () {
|
||
|
const child = this.$slots.overlay[0]
|
||
|
const events = getEvents(child)
|
||
|
if (!events._ANT_DROPDOWN_EVENT_HACK) {
|
||
|
this.childOriginEvents = events
|
||
|
}
|
||
|
const { prefixCls } = this.$props
|
||
|
const extraOverlayProps = {
|
||
|
prefixCls: `${prefixCls}-menu`,
|
||
|
}
|
||
|
const overlay = this.$slots.overlay[0]
|
||
|
return cloneElement(overlay, {
|
||
|
props: extraOverlayProps,
|
||
|
on: {
|
||
|
click: this.onClick,
|
||
|
_ANT_DROPDOWN_EVENT_HACK: () => {},
|
||
|
},
|
||
|
})
|
||
|
},
|
||
|
|
||
|
getPopupDomNode () {
|
||
|
return this.$refs.trigger.getPopupDomNode()
|
||
|
},
|
||
|
|
||
|
afterVisibleChange (visible) {
|
||
|
if (visible && this.$props.minOverlayWidthMatchTrigger) {
|
||
|
const overlayNode = this.getPopupDomNode()
|
||
|
const rootNode = this.$el
|
||
|
if (rootNode && overlayNode && rootNode.offsetWidth > overlayNode.offsetWidth) {
|
||
|
overlayNode.style.width = `${rootNode.offsetWidth}px`
|
||
|
if (this.$refs.trigger &&
|
||
|
this.$refs.trigger._component &&
|
||
|
this.$refs.trigger._component.alignInstance) {
|
||
|
this.$refs.trigger._component.alignInstance.forceAlign()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
},
|
||
|
|
||
|
render () {
|
||
|
const {
|
||
|
prefixCls,
|
||
|
transitionName, animation,
|
||
|
align, placement, getPopupContainer,
|
||
|
showAction, hideAction,
|
||
|
overlayClassName, overlayStyle,
|
||
|
trigger, ...otherProps
|
||
|
} = this.$props
|
||
|
|
||
|
const triggerProps = {
|
||
|
props: {
|
||
|
...otherProps,
|
||
|
prefixCls,
|
||
|
popupClassName: overlayClassName,
|
||
|
popupStyle: overlayStyle,
|
||
|
builtinPlacements: placements,
|
||
|
action: trigger,
|
||
|
showAction,
|
||
|
hideAction,
|
||
|
popupPlacement: placement,
|
||
|
popupAlign: align,
|
||
|
popupTransitionName: transitionName,
|
||
|
popupAnimation: animation,
|
||
|
popupVisible: this.sVisible,
|
||
|
afterPopupVisibleChange: this.afterVisibleChange,
|
||
|
getPopupContainer: getPopupContainer,
|
||
|
},
|
||
|
on: {
|
||
|
popupVisibleChange: this.onVisibleChange,
|
||
|
},
|
||
|
ref: 'trigger',
|
||
|
}
|
||
|
const child = this.$slots.default && this.$slots.default[0]
|
||
|
return (
|
||
|
<Trigger {...triggerProps}>
|
||
|
{child && !child.tag
|
||
|
? <span>{child}</span>
|
||
|
: child}
|
||
|
<template slot='popup'>
|
||
|
{this.$slots.overlay && this.getMenuElement()}
|
||
|
</template>
|
||
|
</Trigger>
|
||
|
)
|
||
|
},
|
||
|
}
|
||
|
|
||
|
</script>
|