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


Posted in Javascript onOctober 20, 2017

前言

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

效果图如下:

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

总结

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

Javascript 相关文章推荐
从阶乘函数对比Javascript和C#的异同
May 31 Javascript
js判断是否按下了Shift键的方法
Jan 27 Javascript
JavaScript将字符串转换成字符编码列表的方法
Mar 19 Javascript
jquery仅用6行代码实现滑动门效果
Sep 07 Javascript
require、backbone等重构手机图片查看器
Nov 17 Javascript
SelecT下拉框选中和取值的解决方法
Nov 22 Javascript
jquery实现焦点轮播效果
Feb 23 Javascript
基于rem的移动端响应式适配方案(详解)
Jul 07 Javascript
Vue异步加载about组件
Oct 31 Javascript
Angular CLI在Angular项目中如何使用scss详解
Apr 10 Javascript
微信小程序实现商城倒计时
Nov 01 Javascript
小程序实现按下录音松开识别语音
Nov 22 Javascript
浅谈如何使用 webpack 优化资源
Oct 20 #Javascript
利用jQuery实现简单的拖曳效果实例代码
Oct 20 #jQuery
Js利用prototype自定义数组方法示例
Oct 20 #Javascript
js 中rewrap-ajax.js插件实例代码
Oct 20 #Javascript
jQuery访问浏览器本地存储cookie、localStorage和sessionStorage的基本用法
Oct 20 #jQuery
JS 中使用Promise 实现红绿灯实例代码(demo)
Oct 20 #Javascript
用JavaScript做简易的购物车的代码示例
Oct 20 #Javascript
You might like
一棵php的类树(支持无限分类)
2006/10/09 PHP
php 强制下载文件实现代码
2013/10/28 PHP
php+xml编程之xpath的应用实例
2015/01/24 PHP
php通过获取头信息判断图片类型的方法
2015/06/26 PHP
php微信公众号开发之二级菜单
2018/10/20 PHP
linux mint下安装phpstorm2020包括JDK部分的教程详解
2020/09/17 PHP
js 新浪的一个图片播放图片轮换效果代码
2008/07/15 Javascript
$.ajax json数据传递方法
2008/11/19 Javascript
javascript 的Document属性和方法集合
2010/01/25 Javascript
jQuery 处理表单元素的代码
2010/02/15 Javascript
js浮点数保留两位小数点示例代码(四舍五入)
2013/12/26 Javascript
jquery中append()与appendto()用法分析
2014/11/14 Javascript
jquery制作图片时钟特效
2020/03/30 Javascript
详解JavaScript 中的 replace 方法
2016/01/01 Javascript
jQueryUI DatePicker 添加时分秒
2016/06/04 Javascript
原生JS封装ajax 传json,str,excel文件上传提交表单(推荐)
2016/06/21 Javascript
微信小程序 教程之小程序配置
2016/10/17 Javascript
Mac 安装 nodejs方法(图文详细步骤)
2017/10/30 NodeJs
详解Angular6学习笔记之主从组件
2018/09/05 Javascript
微信小程序实现左滑修改、删除功能
2020/10/19 Javascript
php结合js实现多条件组合查询
2019/05/28 Javascript
ionic2.0双击返回键退出应用
2019/09/17 Javascript
Python装饰器的函数式编程详解
2015/02/27 Python
使用Python的PIL模块来进行图片对比
2016/02/18 Python
Python实现的堆排序算法示例
2018/04/29 Python
Python基于mysql实现学生管理系统
2019/02/21 Python
Python中利用LSTM模型进行时间序列预测分析的实现
2019/07/26 Python
Django添加bootstrap框架时无法加载静态文件的解决方式
2020/03/27 Python
Python绘图之柱形图绘制详解
2020/07/28 Python
pycharm激活方法到2099年(激活流程)
2020/09/22 Python
ECOSUSI官网:女式皮革背包
2019/09/27 全球购物
开业庆典答谢词
2014/01/18 职场文书
求职自我推荐信
2014/06/25 职场文书
银行转正自我鉴定
2014/09/29 职场文书
XX部保密工作制度范本
2019/08/27 职场文书
《正面管教》读后有感:和善而坚定的旅程
2019/12/19 职场文书