详解vue之better-scroll实现轮播图和页面滚动

来源:互联网 发布:无线摄像头破解软件 编辑:程序博客网 时间:2024/06/06 02:37

(该方法只针对移动端使用效果较好,PC端不推荐,使用的版本是better-scroll@0.1.15,其他版本会出错)

1.安装better-scroll

在根目录中package.json的dependencies中添加:

"better-scroll": "^0.1.15"

然后 npm i 安装。

2.封装代码

将better-scroll封装成两个基础组件slider和scroll放于src/base文件夹中。
slider.vue 代码

<template>  <div class="slider" ref="slider">    <div class="slider-group" ref="sliderGroup">      <slot>      </slot>    </div>    <div class="dots">      <span class="dot" :class="{active: currentPageIndex === index }" v-for="(item, index) in dots"></span>    </div>  </div></template><script>  import {addClass} from '../common/js/dom'  import BScroll from 'better-scroll'  export default{    data() {      return {        dots:[],        currentPageIndex: 0      }    },    props:{      loop:{        type:Boolean,        default:true      },      autoPlay:{        type:Boolean,        default:true      },      interval:{        type: Number,        default:4000      }    },    mounted() {      this._setSliderWidth()      setTimeout(() => {        // 在初始化slider前初始化dot        this._initDots()        this._initSlider()        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        // slider 可见宽度        let sliderWidth = this.$refs.slider.clientWidth        for (let 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        })        // 监听滚动结束时间获取pageX        this.slider.on('scrollEnd', () => {          let pageIndex = this.slider.getCurrentPage().pageX          if (this.loop) {            // 由于bscroll循环播放首尾各加一个,因此索引-1            pageIndex -= 1          }          this.currentPageIndex = pageIndex          if (this.autoPlay) {            this._play()          }        })        this.slider.on('beforeScrollStart', () => {          if (this.autoPlay) {            clearTimeout(this.timer)          }        })      },      _initDots() {        // 长度为n的空数组        this.dots = new Array(this.children.length)      },      _play() {        // currentPageIndex为不含首尾副本的索引,因此若有循环要+2        let pageIndex = this.currentPageIndex + 1        if (this.loop) {          pageIndex += 1        }        this.timer = setTimeout(() => {          this.slider.goToPage(pageIndex, 0, 400)        }, this.interval)      }    },    // 生命周期destroyed销毁清除定时器,有利于内存释放    destroyed() {      clearTimeout(this.timer)    },  }</script><style scoped>  .slider{    min-height: 1px;    position: relative;  }  .slider-group{    position: relative;    overflow: hidden;    white-space: nowrap;  }  .slider-item{    float: left;    box-sizing: border-box;    overflow: hidden;    text-align: center;    height: 150px;    overflow: hidden;  }  .slider-item a{    display: block;    width: 100%;    overflow: hidden;    text-decoration: none;  }  .slider-item img{    display: block;    width: 100%;  }  .dots{    position: absolute;    right: 0;    left: 0;    bottom: 12px;    text-align: center;    font-size: 0;  }  .dot{    display: inline-block;    margin: 0 4px;    width: 8px;    height: 8px;    border-radius: 50%;    background: red;  }  .active{    width: 20px;    border-radius: 5px;  }</style>

该代码引用common/js/dom.js中的addClass()方法为每个轮播图添加一个slider-item类,dom.js代码如下:

export function hasClass (el, className) {  // 开始或空白字符+类名+空白字符或结束  let reg = new RegExp('(^|\\s)' + className + '(\\s|$)')  // 测试元素是否有该类名,返回布尔值  return reg.test(el.className)}export function addClass (el, className) {  if (hasClass(el, className)) {    return  }// 以空白符为切割位置切割生成新数组  let newClass = el.className.split(' ')// 数组中加入新类名  newClass.push(className)// 将数组元素放入一个字符串,以空白符间隔  el.className = newClass.join(' ')}

scroll.vue代码

<template>  <div ref="wrapper">    <slot></slot>  </div></template><script>  import BScroll from 'better-scroll'  export default {    props: {      probeType: {        type: Number,        default: 1      },      click: {        type: Boolean,        default: true      },      listenScroll: {        type: Boolean,        default: false      },      object: {        type: Object,        default: null      },      data: {        type: Array,        default: null      },      string: {        type: String,        default: ''      },      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          // pos为位置参数          this.scroll.on('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')          })        }      },      disable() {        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)      },      string() {        setTimeout(() => {          this.refresh()        }, this.refreshDelay)      },      object() {        setTimeout(() => {          this.refresh()        }, this.refreshDelay)      }    }  }</script><style></style>

3.使用封装组件

使用这两个组件的页面组件home.vue 代码如下:

<template>    <div>    <scroll :data="su" class="scroll">        <div>            <div class="slider-wrapper">                <slider>                    <div v-for='item in slider'>                        <a href="">                            <img :src="item.url" alt="">                        </a>                    </div>                </slider>            </div>            <ul v-for='item in su'>                <li>{{item}}</li>            </ul>        </div>    </scroll>    </div></template><script>    import Slider from '../base/slider'    import Scroll from '../base/scroll'export default {    data () {        return {            slider: [                {url: 'http://upload-images.jianshu.io/upload_images/7932253-54c81df0beed405b.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1080/q/50'},                {url: 'https://y.gtimg.cn/music/photo_new/T003R720x288M000004ERTpn1UBu2f.jpg?max_age=2592000&max_age=2592000'},                {url: 'https://y.gtimg.cn/music/photo_new/T003R720x288M00000077s7P0HaZpc.jpg?max_age=2592000&max_age=2592000'},                {url: 'https://y.gtimg.cn/music/photo_new/T003R720x288M000001QL1Si05yMPq.jpg?max_age=2592000&max_age=2592000'},                {url: 'https://y.gtimg.cn/music/photo_new/T003R720x288M000002ke7OC3ooZ5g.jpg?max_age=2592000&max_age=2592000'},            ],            su:[1,2,3,4,5,6,7,8,9,10,1,2,3,4,2,3,5,8,7,4,]        }    },    methods: {    },    components: {        Slider,        Scroll    }}</script><style>.slider-wrapper{    width: 100%;    position: relative;    overflow: hidden;}.scroll{    height: 500px;}</style>

注意点:

  • slider组件的父元素必须给他一个100%的宽度且定义overflow:hidden,否则整个页面会被撑开,整个页面都能横向滚动
  • scroll组件在引用时必须给他一个固定高度。只有拥有固定高度才会发生滚动。

效果图如下:

原创粉丝点击