/** * @file vue-awesome-swiper * @module SwiperComponent * @author Surmon */ import Vue, { PropType, VNode, CreateElement } from 'vue' import Swiper, { SwiperOptions } from 'swiper' import { DEFAULT_CLASSES, CoreNames, ComponentPropNames, ComponentEvents } from './constants' import { handleClickSlideEvent, bindSwiperEvents } from './event' enum SlotNames { ParallaxBg = 'parallax-bg', Pagination = 'pagination', Scrollbar = 'scrollbar', PrevButton = 'button-prev', NextButton = 'button-next' } export default function getSwiperComponent(SwiperClass: typeof Swiper) { return Vue.extend({ name: CoreNames.SwiperComponent, props: { defaultOptions: { type: Object as PropType, required: false, default: () => ({} as SwiperOptions) }, // eslint-disable-next-line vue/require-default-prop options: { type: Object as PropType, required: false }, [ComponentPropNames.AutoUpdate]: { type: Boolean, default: true }, // https://github.com/surmon-china/vue-awesome-swiper/pull/550/files [ComponentPropNames.AutoDestroy]: { type: Boolean, default: true }, // https://github.com/surmon-china/vue-awesome-swiper/pull/388 [ComponentPropNames.DeleteInstanceOnDestroy]: { type: Boolean, required: false, default: true }, [ComponentPropNames.CleanupStylesOnDestroy]: { type: Boolean, required: false, default: true } }, data() { return { [CoreNames.SwiperInstance as const]: null as Swiper | null } }, computed: { swiperInstance: { cache: false, set(swiper: Swiper) { this[CoreNames.SwiperInstance] = swiper }, get(): Swiper | null { return this[CoreNames.SwiperInstance] } }, swiperOptions(): SwiperOptions { return this.options || this.defaultOptions }, wrapperClass(): string { return this.swiperOptions.wrapperClass || DEFAULT_CLASSES.wrapperClass } }, methods: { // Feature: click event handleSwiperClick(event: MouseEvent) { handleClickSlideEvent( this.swiperInstance, event, this.$emit.bind(this) ) }, autoReLoopSwiper() { if (this.swiperInstance && this.swiperOptions.loop) { // https://github.com/surmon-china/vue-awesome-swiper/issues/593 // https://github.com/surmon-china/vue-awesome-swiper/issues/544 // https://github.com/surmon-china/vue-awesome-swiper/pull/545/files const swiper = this.swiperInstance as any swiper?.loopDestroy?.() swiper?.loopCreate?.() } }, updateSwiper() { if (this[ComponentPropNames.AutoUpdate] && this.swiperInstance) { this.autoReLoopSwiper() this.swiperInstance?.update?.() this.swiperInstance.navigation?.update?.() this.swiperInstance.pagination?.render?.() this.swiperInstance.pagination?.update?.() } }, destroySwiper() { if (this[ComponentPropNames.AutoDestroy] && this.swiperInstance) { // https://github.com/surmon-china/vue-awesome-swiper/pull/341 // https://github.com/surmon-china/vue-awesome-swiper/issues/340 if ((this.swiperInstance as any).initialized) { this.swiperInstance?.destroy?.( this[ComponentPropNames.DeleteInstanceOnDestroy], this[ComponentPropNames.CleanupStylesOnDestroy] ) } } }, initSwiper() { this.swiperInstance = new SwiperClass( this.$el as HTMLElement, this.swiperOptions ) bindSwiperEvents( this.swiperInstance, this.$emit.bind(this) ) this.$emit( ComponentEvents.Ready, this.swiperInstance ) } }, mounted() { if (!this.swiperInstance) { this.initSwiper() } }, // Update swiper when the parent component activated with `keep-alive`. activated() { this.updateSwiper() }, updated() { this.updateSwiper() }, beforeDestroy() { // https://github.com/surmon-china/vue-awesome-swiper/commit/2924a9d4d3d1cf51c0d46076410b1f804b2b8a43#diff-7f4e0261ac562c0f354cb91a1ca8864f this.$nextTick(this.destroySwiper) }, render(createElement: CreateElement): VNode { return createElement('div', { staticClass: DEFAULT_CLASSES.containerClass, on: { click: this.handleSwiperClick } }, [ this.$slots[SlotNames.ParallaxBg], createElement('div', { class: this.wrapperClass }, this.$slots.default), this.$slots[SlotNames.Pagination], this.$slots[SlotNames.PrevButton], this.$slots[SlotNames.NextButton], this.$slots[SlotNames.Scrollbar] ] ) } }) }