ant-design-vue/components/align/Align.jsx

128 lines
3.1 KiB
React
Raw Normal View History

2018-03-19 02:16:27 +00:00
2017-12-26 11:04:28 +00:00
import PropTypes from '../_util/vue-types'
2017-12-12 07:05:45 +00:00
import align from 'dom-align'
import addEventListener from '../_util/Dom/addEventListener'
2017-12-14 04:13:15 +00:00
import { cloneElement } from '../_util/vnode.js'
2017-12-13 02:06:26 +00:00
import isWindow from './isWindow'
2018-03-22 09:23:51 +00:00
import clonedeep from 'lodash/cloneDeep'
2018-03-14 02:36:52 +00:00
import shallowequal from 'shallowequal'
2017-12-12 07:05:45 +00:00
function noop () {
}
function buffer (fn, ms) {
let timer
function clear () {
if (timer) {
clearTimeout(timer)
timer = null
}
}
function bufferFn () {
clear()
timer = setTimeout(fn, ms)
}
bufferFn.clear = clear
return bufferFn
}
export default {
props: {
childrenProps: PropTypes.object,
align: PropTypes.object.isRequired,
target: PropTypes.func.def(noop),
monitorBufferTime: PropTypes.number.def(50),
monitorWindowResize: PropTypes.bool.def(false),
disabled: PropTypes.bool.def(false),
2018-02-22 09:19:47 +00:00
visible: PropTypes.bool.def(false),
2017-12-12 07:05:45 +00:00
},
2018-01-15 09:33:34 +00:00
data () {
2018-01-16 07:41:00 +00:00
this.aligned = false
2018-01-15 09:33:34 +00:00
return {
}
2017-12-13 02:06:26 +00:00
},
2017-12-12 07:05:45 +00:00
mounted () {
2018-02-27 04:17:53 +00:00
this.$nextTick(() => {
this.prevProps = { ...this.$props }
const props = this.$props
// if parent ref not attached .... use document.getElementById
!this.aligned && this.forceAlign()
if (!props.disabled && props.monitorWindowResize) {
this.startMonitorWindowResize()
}
})
2017-12-12 07:05:45 +00:00
},
2018-01-15 09:33:34 +00:00
updated () {
2018-02-27 04:17:53 +00:00
this.$nextTick(() => {
const prevProps = this.prevProps
const props = this.$props
let reAlign = false
if (!props.disabled && this.visible) {
2018-03-14 02:36:52 +00:00
if (prevProps.disabled || !shallowequal(prevProps.align, props.align)) {
2018-01-15 09:33:34 +00:00
reAlign = true
2018-02-27 04:17:53 +00:00
} else {
const lastTarget = prevProps.target()
const currentTarget = props.target()
if (isWindow(lastTarget) && isWindow(currentTarget)) {
reAlign = false
} else if (lastTarget !== currentTarget) {
reAlign = true
}
2018-01-15 09:33:34 +00:00
}
}
2018-02-27 04:17:53 +00:00
if (reAlign) {
this.forceAlign()
}
2018-01-15 09:33:34 +00:00
2018-02-27 04:17:53 +00:00
if (props.monitorWindowResize && !props.disabled) {
this.startMonitorWindowResize()
} else {
this.stopMonitorWindowResize()
}
2018-03-14 02:36:52 +00:00
this.prevProps = { ...this.$props, align: clonedeep(this.$props.align) }
2018-02-27 04:17:53 +00:00
})
2018-01-15 09:33:34 +00:00
},
2017-12-13 02:06:26 +00:00
beforeDestroy () {
2017-12-12 07:05:45 +00:00
this.stopMonitorWindowResize()
},
methods: {
startMonitorWindowResize () {
if (!this.resizeHandler) {
this.bufferMonitor = buffer(this.forceAlign, this.$props.monitorBufferTime)
this.resizeHandler = addEventListener(window, 'resize', this.bufferMonitor)
}
},
stopMonitorWindowResize () {
if (this.resizeHandler) {
this.bufferMonitor.clear()
this.resizeHandler.remove()
this.resizeHandler = null
}
},
forceAlign () {
const props = this.$props
if (!props.disabled) {
const source = this.$el
2018-01-15 09:33:34 +00:00
this.aligned = true
2018-01-12 08:10:41 +00:00
this.$listeners.align && this.$listeners.align(source, align(source, props.target(), props.align))
2017-12-12 07:05:45 +00:00
}
},
},
render () {
const { childrenProps } = this.$props
const child = this.$slots.default[0]
if (childrenProps) {
2017-12-25 10:08:36 +00:00
return cloneElement(child, { props: childrenProps })
2017-12-12 07:05:45 +00:00
}
return child
},
}