首页 > 编程 > JavaScript > 正文

vue利用better-scroll实现轮播图与页面滚动详解

2019-11-19 15:07:34
字体:
来源:转载
供稿:网友

前言

better-scroll 也很强大,不仅可以做普通的滚动列表,还可以做轮播图、picker 等等...所以本文主要给大家介绍了关于vue用better-scroll实现轮播图与页面滚动的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

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组件在引用时必须给他一个固定高度。只有拥有固定高度才会发生滚动。

效果图如下:


总结

以上就是这篇文章的全部内容了,本文还有许多不足,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对武林网的支持。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表