You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
81 lines
1.7 KiB
81 lines
1.7 KiB
import Vue from 'vue'
|
|
import { ItemProps, SlotProps } from './props'
|
|
|
|
const Wrapper = {
|
|
created() {
|
|
this.shapeKey = this.horizontal ? 'offsetWidth' : 'offsetHeight'
|
|
},
|
|
|
|
mounted() {
|
|
if (typeof ResizeObserver !== 'undefined') {
|
|
this.resizeObserver = new ResizeObserver(() => {
|
|
this.dispatchSizeChange()
|
|
})
|
|
this.resizeObserver.observe(this.$el)
|
|
}
|
|
},
|
|
|
|
// since component will be reused, so dispatch when updated
|
|
updated() {
|
|
this.dispatchSizeChange()
|
|
},
|
|
|
|
beforeDestroy() {
|
|
if (this.resizeObserver) {
|
|
this.resizeObserver.disconnect()
|
|
this.resizeObserver = null
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
getCurrentSize() {
|
|
return this.$el ? this.$el[this.shapeKey] : 0
|
|
},
|
|
|
|
// tell parent current size identify by unique key
|
|
dispatchSizeChange() {
|
|
this.$parent.$emit(this.event, this.uniqueKey, this.getCurrentSize(), this.hasInitial)
|
|
}
|
|
}
|
|
}
|
|
|
|
// wrapping for item
|
|
export const Item = Vue.component('virtual-list-item', {
|
|
mixins: [Wrapper],
|
|
|
|
props: ItemProps,
|
|
|
|
render(h) {
|
|
const { tag, component, extraProps = {}, index, scopedSlots = {}, uniqueKey } = this
|
|
extraProps.source = this.source
|
|
extraProps.index = index
|
|
|
|
return h(tag, {
|
|
key: uniqueKey,
|
|
attrs: {
|
|
role: 'item'
|
|
}
|
|
}, [h(component, {
|
|
props: extraProps,
|
|
scopedSlots: scopedSlots
|
|
})])
|
|
}
|
|
})
|
|
|
|
// wrapping for slot
|
|
export const Slot = Vue.component('virtual-list-slot', {
|
|
mixins: [Wrapper],
|
|
|
|
props: SlotProps,
|
|
|
|
render(h) {
|
|
const { tag, uniqueKey } = this
|
|
|
|
return h(tag, {
|
|
key: uniqueKey,
|
|
attrs: {
|
|
role: uniqueKey
|
|
}
|
|
}, this.$slots.default)
|
|
}
|
|
}) |