better-scroll项目中遇到的问题
官网:https://better-scroll.github.io/docs/zh-CN/
与better-scroll有关的文档:https://juejin.im/post/5e40f72df265da5732551bdf#heading-5
1、在项目中发现个问题,用better-scroll实现的轮播图和页面滚动条俩个效果一起出现的时候,当鼠标或手指放在轮播图位置的时候,上下滚动的时候,页面滚动条不动
发现最新的版本就会出这个问题,就是官网的例子中也一样,还有cube-ui中的轮播图
https://ustbhuangyi.github.io/better-scroll/#/examples/slide/en
解决办法是:
第一种:轮播图用其他的,不要用better-sacroll,比如可以使用vant里面的轮播图效果https://youzan.github.io/vant/#/zh-CN/swipe。页面滚动效果用better-sacroll的
这有个问题:如果我们的轮播图可以点击跳转,那么在滑动的时候,会触发跳转效果。这时我们就需要做处理,比如给跳转加一个时间判断(感觉这样挺麻烦的)
第二种:不要用新版本的better-scroll,可以使用0.4.0版本的
第三种: 也是现阶段我认为最好的
在于scrollX平级的地方,不要stopPropagation这个属性,如果还不行,就加一个eventPassthrough: 'vertical'
示例代码:
<template> <div class="slider" ref="slide"> <div class="slider-group" ref="slideGroup"> <slot> </slot> </div> <div v-if="showDot" class="dots" :class="{dots_center : (dots_position === 0),dots_left : (dots_position === 1),dots_right : (dots_position === 2)}"> <span class="dot" :class="{active: currentPageIndex === index }" v-for="(item, index) in dots" :key="index"></span> </div> </div> </template> <script type="text/ecmascript-6"> import {addClass} from 'common/js/dom.js' import BScroll from 'better-scroll' import {mapMutations} from 'vuex' export default { name: 'slider', props: { autoPlay: { // 是否开启自动滚动 type: Boolean, default: true }, loop: { // 是否开启循环滚动 type: Boolean, default: true }, interval: { // 滚动间隔时间 type: Number, default: 4000 }, showDot: { type: Boolean, default: true }, click: { type: Boolean, default: true }, threshold: { type: Number, default: 0.3 }, speed: { type: Number, default: 400 }, dots_position: { // 焦点的位置 0 中间 1 左边 2 右边 type: Number, default: 0 }, showItemIndex: { type: Number, defalut: 0 } }, data() { return { dots: [], currentPageIndex: 0 } }, mounted() { this.update() window.addEventListener('resize', () => { if (!this.slide || !this.slide.enabled) { return } clearTimeout(this.resizeTimer) this.resizeTimer = setTimeout(() => { if (this.slide.isInTransition) { this._onScrollEnd() } else { if (this.autoPlay) { this._play() } } this.refresh() }, 60) }) }, activated() { if (!this.slide) { return } this.slide.enable() let pageIndex = this.slide.getCurrentPage().pageX this.slide.goToPage(pageIndex, 0, 0) this.currentPageIndex = pageIndex if (this.autoPlay) { this._play() } }, deactivated() { this.slide.disable() clearTimeout(this.timer) }, beforeDestroy() { this.slide.disable() clearTimeout(this.timer) }, methods: { update() { if (this.slide) { this.slide.destroy() } this.$nextTick(() => { this.init() }) }, refresh() { this._setSlideWidth(true) this.slide.refresh() }, prev() { this.slide.prev() }, next() { this.slide.next() }, init() { clearTimeout(this.timer) this.currentPageIndex = 0 this._setSlideWidth() if (this.showDot) { this._initDots() } this._initSlide() if (this.autoPlay) { this._play() } }, _setSlideWidth(isResize) { this.children = this.$refs.slideGroup.children let width = 0 let slideWidth = this.$refs.slide.clientWidth for (let i = 0; i < this.children.length; i++) { let child = this.children[i] addClass(child, 'slider-item') child.style.width = slideWidth + 'px' width += slideWidth } if (this.loop && !isResize) { width += 2 * slideWidth } this.$refs.slideGroup.style.width = width + 'px' }, _initSlide() { this.slide = new BScroll(this.$refs.slide, { scrollX: true, scrollY: false, eventPassthrough: 'vertical', momentum: false, snap: { loop: this.loop, threshold: this.threshold, speed: this.speed }, bounce: false, click: this.click, freeScroll: true }) this.slide.on('scrollEnd', this._onScrollEnd) this.slide.on('touchEnd', () => { if (this.autoPlay) { this._play() } }) this.slide.on('beforeScrollStart', () => { if (this.autoPlay) { clearTimeout(this.timer) } }) }, _onScrollEnd() { let pageIndex = this.slide.getCurrentPage().pageX this.currentPageIndex = pageIndex if (this.autoPlay) { this._play() } else { // 触发回调,将当前index值作为参数返回到store中 this.saveSIndex(this.currentPageIndex + 1) } }, ...mapMutations({ saveSIndex: 'SET_SLIDERINDEX' }), _initDots() { this.dots = new Array(this.children.length) }, _play() { clearTimeout(this.timer) this.timer = setTimeout(() => { this.slide.next() }, this.interval) } }, watch: { loop() { this.update() }, autoPlay() { this.update() }, speed() { this.update() }, threshold() { this.update() }, showItemIndex (index) { this.slide.goToPage(index, 0, 0) } } } </script> <style lang="less" rel="stylesheet/less" type="text/less"> @import "../../common/less/variable"; .slider{ min-height: 1px; } .slider-group{ position: relative; overflow: hidden; white-space: nowrap; } .slider-item{ float: left; box-sizing: border-box; overflow: hidden; text-align: center; } .slider-item a{ display: block; width: 100%; overflow: hidden; text-decoration: none; } .slider-item img{ display: block; width: 100%; } .dots{ position: absolute; bottom: 30px; transform: translateZ(1px); font-size: 0; } .dots_center{ left: 0; right: 0; } .dots_left{ left: 30px; } .dots_right{ right: 30px; } .dot{ display: inline-block; margin: 0 8px; width: 10px; height: 10px; border: 2px solid #f8fafc; border-radius: 50%; background: rgba(255, 255, 255, 0.5); } .dot.active{ background: #398ed1; } </style>