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