vue组件库
Slider 轮播图组件
基于Better-scroll
的轮播组件,所以必须首先安装 better-scroll
// slider.vue
<template>
<!-- 轮播图组件 -->
<div class="slider" ref="slider">
<!-- images -->
<div class="slider-group" ref="sliderGroup">
<slot></slot>
</div>
<!-- dots -->
<div class="dots">
<span class="dot-item"
v-for="(item, index) in dots"
:key="index"
:class="{'active': currentDotIndex === index}"
></span>
</div>
</div>
</template>
<script>
import {addClass} from '@/common/js/Dom'
import BScroll from 'better-scroll'
export default {
name: 'slider',
props: {
loop: {
type: Boolean, // 循环播放
default: true
},
autoPlay: {
type: Boolean, // 自动播放
default: true
},
interval: {
type: Number, // 滚动的时间间隔
default: 4000
}
},
data() {
return {
dots: [],
currentDotIndex: 0
}
},
mounted() {
setTimeout(() => {
this._setSliderWidth()
this._initDots()
this._initSlider()
if (this.autoPlay) {
this._play()
}
}, 20)
// 当窗口发生变化的时候
window.addEventListener('resize', () => {
if (!this.slider) {
return false
}
this._setSliderWidth(true)
this.slider.refresh()
})
},
activated () {
if (this.autoPlay) {
this._play()
}
},
deactivated () {
clearTimeout(this.timer)
},
beforeDestroy () {
clearTimeout(this.timer)
},
methods: {
_setSliderWidth (isResize) {
// 初始化宽度
// 获取每一张图片DOM
this.children = this.$refs.sliderGroup.children
let width = 0
let sliderWidth = this.$refs.slider.clientWidth // 每一张图片的宽度
for (let i = 0; i < this.children.length; i++) {
let child = this.children[i]
addClass(child, 'slider-item') // 添加class
child.style.width = sliderWidth + 'px' // 设置宽度
width += sliderWidth // 求和算出总宽度
}
if (this.loop && !isResize) {
width += 2 * sliderWidth // 循环增加
}
// 设置图片的直接容器的宽度
this.$refs.sliderGroup.style.width = width + 'px'
},
_initSlider () {
// 实例化一个 better-scroll对象
this.slider = new BScroll(this.$refs.slider, {
scrollX: true,
scrollY: false,
momentum: false, // 快速滑动不开启滑动惯性 ,默认式true
snap: {
loop: this.loop, // 为了支持循环轮播
threshold: 0.3, // 表示可滚动到下一个的阈值
speed: 400 // 轮播图切换的动画时间
},
click: true
})
// 一页图片滚动完毕之后触发
this.slider.on('scrollEnd', () => {
let pageIndex = this.slider.getCurrentPage().pageX
this.currentDotIndex = pageIndex
if (this.autoPlay) {
// 用手拖的时候清除定时器
clearTimeout(this.timer)
this._play()
}
})
},
_initDots () {
this.dots = new Array(this.children.length)
},
_play () {
// 自动播放
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.slider.next()
}, this.interval)
}
}
}
</script>
<style lang="stylus" scoped>
@import "../../common/stylus/varstyle.styl"
.slider
min-height: 1px
position relative
.slider-group
width: 100%
position relative
overflow hidden
white-space nowrap
.slider-item
float left
box-sizing border-box
overflow: hidden
text-align: center
a
display block
width 100%
overflow hidden
text-align center
img
display block
width 100%
.dots
position absolute
left: 0px
right: 0px
bottom 8px
text-align center
font-size 0px
.dot-item
display inline-block
margin 0px 4px
width: 8px
height: 8px
border-radius 50%
background $color-text-l
&.active
width: 12px
border-radius 5px
background $color-text-ll
</style>
使用
//
<template>
<div class="recommend-wrapper">
// 【1】 这里的 v-if 必须写
<div v-if="recommemds.length" class="slider-wrapper" ref="sliderWrapper">
<slider>
<div v-for="(item, index) in recommemds"
:key="index"
>
<a :href="item.linkUrl">
<img :src="item.picUrl" alt="">
</a>
</div>
</slider>
</div>
</div>
</template>
Scroll 区域滚动组件
// scroll.vue
<template>
<!-- 滚动区域组件 -->
<div ref="wrapper">
<slot></slot>
</div>
</template>
<script type="text/ecmascript-6">
import BScroll from 'better-scroll'
export default {
props: {
probeType: {
type: Number,
default: 1
},
click: {
type: Boolean,
default: true
},
listenScroll: {
type: Boolean,
default: false
},
data: {
type: Array,
default: null
},
pullup: {
type: Boolean,
default: false
},
beforeScroll: {
type: Boolean,
default: false
},
refreshDelay: {
type: Number,
default: 20
}
},
mounted () {
setTimeout(() => {
this._initScroll()
}, 20)
},
methods: {
_initScroll () {
// 初始化
if (!this.$refs.wrapper) {
return
}
// 实例化一个对象
this.scroll = new BScroll(this.$refs.wrapper, {
probeType: this.probeType,
click: this.click
})
// 如果监听
if (this.listenScroll) {
let me = this
// 监听scroll事件
this.scroll.on('scroll', (pos) => {
// 派发一个scroll事件, 传出pos参数
me.$emit('scroll', pos)
})
}
if (this.pullup) {
// 向下滚动监听时候滚动结束
this.scroll.on('scrollEnd', () => {
if (this.scroll.y <= (this.scroll.maxScrollY + 50)) {
// 派发事件
this.$emit('scrollToEnd')
}
})
}
if (this.beforeScroll) {
// 监听滚动之前
this.scroll.on('beforeScrollStart', () => {
this.$emit('beforeScroll')
})
}
},
// 下面是代理了一些better-scroll的方法
disable () {
// 也就是说,调用当前组件的方法就是在调用better-scroll的原生的方法
this.scroll && this.scroll.disable()
},
enable () {
this.scroll && this.scroll.enable()
},
refresh () {
this.scroll && this.scroll.refresh()
},
scrollTo () {
this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments)
},
scrollToElement () {
this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments)
}
},
watch: {
// 监听数据
data () {
// 自动刷新
setTimeout(() => {
this.refresh()
}, this.refreshDelay)
}
}
}
</script>
<style scoped lang="stylus" rel="stylesheet/stylus">
</style>
使用
// 必须通过css规定大小哦,并且需要设置overflow: hidden;
<scroll class="recommend-wrapper" :data="discList">
<div>
// 数据内容
</div>
</scroll>