<template>
<div class="swiper-container" :id="slideId">
<slot name="parallax"></slot>
<div class="swiper-wrapper">
<slot></slot>
</div>
<!-- Add Pagination -->
<div v-if="pagination" :class="paginationClass"></div>
<!-- Add Arrows -->
<div v-if="prevButton" :class="prevButtonClass"></div>
<div v-if="nextButton" :class="nextButtonClass"></div>
<!-- Add Scrollbar -->
<div v-if="scrollbar" :class="scrollbarClass"></div>
</div>
</template>
<style lang="scss" src="./style.scss"></style>
<script type="text/javascript">
/**
* @component Slides
* @description
*
* ## 轮播组件 / Slides
*
* 这部分是移植Swiper插件, 因此两者的API完全移植, 即: Swiper初始化传入的参数/发出的事件都可在Slides中使用.
*
* ### Vue组件传参及Swiper初始化的概念互通
*
* Swiper插件在初始化的时候需要传入轮播HTML结构的信息, 之后传入初始化对象. 初始化对象包括**属性参数**和**钩子事件参数**, 因此在向Vue组件迁移则为这样:
*
* - 属性部分对应Vue组件的props
* - 钩子时间部分对应Vue组件的事件系统
*
* 此外, swiper初始化的部分交由slides组件处理, 并且组件自行记录Swiper的id, 默认id从0开始.
*
* ### 关于
*
* 关于props被修改的报错, 这部分暂时未处理, 且即使报错也能正常build. 去除报错就是按照错误提示将此props值手动传入即可(比如定义effect属性).
*
* ### 最后
*
* 具体用法请参考Demo, Swiper API请参考下面的文档. 另外, Swiper实例化会对resize事件监听, 这是因为存在屏幕翻转的情况.
*
* ### 如何获取swiper示例
*
* 使用ref获取组件实例
*
* ```
* dynamicSlidesComponent () {
* return this.$refs.dynamicSlides.swiper
* }
* ```
*
* ### 如何使用
*
* ```
* // 引入
* import { Slides, Slide } from 'vimo'
* // 安装
* Vue.component(Slides.name, Slides)
* Vue.component(Slide.name, Slide)
* ```
*
* @slot [parallax] - 当定义视差时, 需要这个插槽
*
* @usage
* <!-- 比如: 需要左右两个翻页Button和下面的pagination, pagination可点击, 且自动播放间隔2500ms, 页面间距30px, 此外还要要在onInit事件处理相关业务 -->
* <h5>Autoplay</h5>
* <Slides class="swiper"
* @ onInit="onInitHandler"
* nextButton=".swiper-button-next"
* prevButton=".swiper-button-prev"
* pagination=".swiper-pagination"
* :paginationClickable="true"
* :centeredSlides="true"
* :autoplay="2500"
* :autoplayDisableOnInteraction="false"
* :spaceBetween="30">
* <!-- 幻灯内容 -->
* <Slide class="slide">
* <img src="../../static/img/scenery_1.jpg">
* </Slide>
* <Slide class="slide">
* <img src="../../static/img/scenery_2.jpg">
* </Slide>
* <Slide class="slide">
* <img src="../../static/img/scenery_3.jpg">
* </Slide>
* </Slides>
*
* .....
*
* methods: {
* onInitHandler(swiper){
* console.debug('Swiper实例: ')
* console.debug(swiper)
* }
* }
*
*
*
* @demo #/slides
* @see http://idangero.us/swiper/api/
*
* */
import Swiper from 'swiper'
import { getEvents, getProps } from './interface'
export default {
name: 'Slides',
provide () {
const _this = this
return {
slidesComponent: _this
}
},
props: getProps(),
data () {
return {
timer: null, // 子组件注册的计时器
swiper: null, // Swiper插件的实例
id: this._uid, // 当前组件的id
init: false // 是否初始化
}
},
computed: {
slideId () {
return 'slides-' + this.id
},
// 指示标志的class
paginationClass () {
if (this.pagination[0] === '.') {
return this.pagination.substr(1)
} else {
console.error('The props of pagination in Slides component need dot in front, like `.swiper-pagination`. ')
return null
}
},
nextButtonClass () {
if (this.nextButton[0] === '.') {
return this.nextButton.substr(1)
} else {
console.error('The props of nextButton in Slides component need dot in front, like `.swiper-button-next`. ')
return null
}
},
prevButtonClass () {
if (this.prevButton[0] === '.') {
return this.prevButton.substr(1)
} else {
console.error('The props of prevButton in Slides component need dot in front, like `.swiper-button-prev`. ')
return null
}
},
scrollbarClass () {
if (this.scrollbar[0] === '.') {
return this.scrollbar.substr(1)
} else {
console.error('The props of scrollbar in Slides component need dot in front, like `.swiper-scrollbar`. ')
return null
}
}
},
methods: {
/**
* 初始化swiper
* @private
* */
initSlides () {
this.timer && window.clearTimeout(this.timer)
this.timer = window.setTimeout(() => {
if (!this.init) {
// 未初始化则创建实例
this.swiper = new Swiper(this.$el, Object.assign({}, this.$options.propsData, getEvents(this)))
this.init = true
} else {
// 已创建实例, 则更新实例
this.swiper && this.swiper.update(true)
}
}, 0)
}
},
destroyed () {
this.swiper && this.swiper.destroy()
}
}
</script>