vue-awesome-swiper
Version:
Swiper component for Vue
170 lines (166 loc) • 5.34 kB
text/typescript
/**
* @file vue-awesome-swiper
* @module SwiperComponent
* @author Surmon <https://github.com/surmon-china>
*/
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<SwiperOptions>,
required: false,
default: () => ({} as SwiperOptions)
},
// eslint-disable-next-line vue/require-default-prop
options: {
type: Object as PropType<SwiperOptions>,
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]
]
)
}
})
}