Browse Source

add align

pull/9/head
tangjinzhou 7 years ago
parent
commit
8736a23884
  1. 5
      components/_util/Dom/addEventListener.js
  2. 4
      components/_util/StateMixin.js
  3. 7
      components/_util/cloneElement.js
  4. 104
      components/align/Align.vue
  5. 81
      components/align/demo/simple.vue
  6. 3
      components/align/index.js
  7. 5
      components/align/isWindow.js

5
components/_util/Dom/addEventListener.js

@ -0,0 +1,5 @@
import addDOMEventListener from 'add-dom-event-listener'
export default function addEventListenerWrap (target, eventType, cb) {
return addDOMEventListener(target, eventType, cb)
}

4
components/_util/StateMixin.js

@ -1,9 +1,9 @@
export default {
methods: {
setState (state, callback) {
Object.assign(this.$date, state)
Object.assign(this.$data, state)
this.$nextTick(() => {
callback()
callback && callback()
})
},
},

7
components/_util/cloneElement.js

@ -0,0 +1,7 @@
export default (node, props) => {
if (node.componentOptions) {
const propsData = node.componentOptions.propsData
Object.assign(propsData, props)
}
return node
}

104
components/align/Align.vue

@ -0,0 +1,104 @@
<script>
import PropTypes from 'vue-types'
import align from 'dom-align'
import addEventListener from '../_util/Dom/addEventListener'
import cloneElement from '../_util/cloneElement'
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),
},
mounted () {
const props = this.$props
// if parent ref not attached .... use document.getElementById
this.forceAlign()
if (!props.disabled && props.monitorWindowResize) {
this.startMonitorWindowResize()
}
},
updated () {
const props = this.$props
this.forceAlign()
if (props.monitorWindowResize && !props.disabled) {
this.startMonitorWindowResize()
} else {
this.stopMonitorWindowResize()
}
},
beforeDestory () {
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
this.$emit('align', source, align(source, props.target(), props.align))
}
},
},
render () {
const { childrenProps } = this.$props
const child = this.$slots.default[0]
if (childrenProps) {
const newProps = {}
for (const prop in childrenProps) {
if (childrenProps.hasOwnProperty(prop)) {
newProps[prop] = this.props[childrenProps[prop]]
}
}
return cloneElement(child, newProps)
}
return child
},
}
</script>

81
components/align/demo/simple.vue

@ -0,0 +1,81 @@
<script>
import Align from '../index'
import StateMixin from '../../_util/StateMixin'
export default {
mixins: [StateMixin],
data () {
return {
monitor: true,
align: {
points: ['tl', 'tc'],
},
}
},
methods: {
getTarget () {
const ref = this.$refs.container
// if (!ref) {
// // parent ref not attached
// ref = document.getElementById('container')
// }
return ref
},
toggleMonitor () {
this.setState({
monitor: !this.$data.monitor,
})
},
forceAlign () {
this.setState({
align: Object.assign({}, this.$data.align),
})
},
},
render () {
return (
<div
style={{
margin: 50,
}}
>
<p>
<button onClick={this.forceAlign}>force align</button>
&nbsp;&nbsp;&nbsp;
<button onClick={this.toggleMonitor}>toggle monitor</button>
</p>
<div
ref='container'
id='container'
style={{
width: '80%',
height: '500px',
border: '1px solid red',
}}
>
<Align
target={this.getTarget}
monitorWindowResize={this.$data.monitor}
align={this.$data.align}
>
<div
style={{
position: 'absolute',
width: '50px',
height: '50px',
background: 'yellow',
}}
>
source
</div>
</Align>
</div>
</div>
)
},
}
</script>

3
components/align/index.js

@ -0,0 +1,3 @@
// export this package's api
import Align from './Align'
export default Align

5
components/align/isWindow.js

@ -0,0 +1,5 @@
export default function isWindow (obj) {
/* eslint no-eq-null: 0 */
/* eslint eqeqeq: 0 */
return obj != null && obj == obj.window
}
Loading…
Cancel
Save