| 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) |
| } |
| }) |