父组件:
<scroll ref="scroll" class="recommend-content" :data="discList">
<div>
<div v-if="recommends.length" class="slider-wrapper" ref="sliderWrapper">
<slider>
<div v-for="item in recommends">
<a :href="item.linkUrl">
<img class="needsclick" @load="loadImage" :src="item.picUrl">
</a>
</div>
</slider>
</div>
<div class="recommend-list">
<h1 class="list-title">热门歌单推荐</h1>
<ul>
<li v-for="item in discList" class="item">
<div class="icon">
<img :src="item.imgurl" width="60" height="60" alt="">
</div>
<div class="text">
<h2 class="name" v-html="item.creator.name"></h2>
<p class="desc" v-html="item.dissname"></p>
</div>
</li>
</ul>
</div>
</div>
</scroll>
import Slider from 'base/slider/slider'
import Scroll from 'base/scroll/scroll'
export default{
methods: {
...
loadImage() {
// 确保只执行一次
if (!this.checkLoaded) {
this.checkLoaded = true;
this.$refs.scroll.refresh()
}
}
},
components: {
Slider,
Scroll
}
}
子组件:
1.slider:
<template>
<div class="slider" ref="slider">
<div class="slider-group" ref="sliderGroup">
<slot></slot>
</div>
<div class="dots">
<div class="dot" v-for="(item,index) in dots" :class="{active: currentPageIndex===index}"></div>
</div>
</div>
</template>
<script type="text/ecmascript-6">
import BScroll from 'better-scroll'
export default {
props: {
loop: {
type: Boolean,
default: true
},
autoPlay: {
type: Boolean,
default: true
},
interval: {
type: Number,
default: 4000
}
},
data() {
return {
dots: [],
currentPageIndex: 0
}
},
created() {},
mounted() {
// 为什么是20ms? 浏览器刷新通常是17ms一次
setTimeout(() => {
this._setSliderWidth();
this._initSlider();
this._initDots();
if (this.autoPlay) {
this._play();
}
}, 20);
window.addEventListener('resize', () => {
if (!this.slider) {
return
}
this._setSliderWidth(true);
this.slider.refresh();
})
},
methods: {
_setSliderWidth(isResize) {
this.children = this.$refs.sliderGroup.children;
let width = 0;
let sliderWidth = this.$refs.slider.clientWidth;
for (var i = 0; i < this.children.length; i++) {
let child = this.children[i]
addClass(child, 'slider-item');
child.style.width = sliderWidth + 'px';
width += sliderWidth;
}
if (this.loop && !isResize) {
width += 2 * sliderWidth;
}
this.$refs.sliderGroup.style.width = width + 'px';
},
_initSlider() {
this.slider = new BScroll(this.$refs.slider, {
scrollX: true,
scrollY: false,
momentum: false,
snap: true,
snapLoop: this.loop,
snapThreshold: 0.3,
snapSpeed: 400,
click: true
})
this.slider.on('scrollEnd', () => {
let pageIndex = this.slider.getCurrentPage().pageX;
if (this.loop) {
pageIndex--;
}
this.currentPageIndex = pageIndex;
if (this.autoPlay) {
clearTimeout(this.timer);
this._play();
}
})
},
_initDots() {
this.dots = this.loop ? new Array(this.children.length - 2) : new Array(this.children.length);
},
_play() {
let pageIndex = ++this.currentPageIndex;
if (this.loop) {
pageIndex++;
}
this.timer = setTimeout(() => {
this.slider.goToPage(pageIndex, 0, 400)
}, this.interval)
}
},
destroyed() {
clearTimeout(this.timer)
}
}
</script>
2.scroll:
<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
},
data: {
type: Array,
default: null
}
},
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
})
},
enable() {
this.scroll && this.scroll.enable()
},
disable() {
this.scroll && this.scroll.disable()
},
refresh() {
this.scroll && this.scroll.refresh()
}
},
watch: {
data() {
setTimeout(() => {
this.refresh()
}, 20)
}
}
}
</script>
<style lang="scss" scoped>
@import "src/common/scss/variable";
</style>