vue.js 使用原生js实现轮播图


Posted in Vue.js onApril 26, 2022

前言

今天我在vue.js项目实战开发过程中遇到了实现轮播图效果的问题,因为不想因为一个轮播图而引用整个jquery,而且我还发现自己根本就不清楚移动端的一些事件,所以我就进行了一些资料查找,并最终解决了这个问题,接下来跟大家分享一下我的解决问题的过程.

一、了解原生js移动端的事件

原生js移动端的事件一共有四种:

事件 作用
touchstart 手指放到屏幕上触发
touchmove 手指在屏幕上移动触发(高频触发)
touchend 手指离开屏幕触发
touchcancel 系统取消touch事件时触发

在每个事件被触发后,会返回一个event参数,event里面包含着三个触摸列表,即:

event中的触摸列表 内容
touches 屏幕上所有的手指列表
targetTouches 当前这个DOM中的手指列表
changedTouches 涉及当前事件的手指列表(本实例中尽量用这个)

触摸列表中每个触摸对象(即每个手指)都对应着一些触摸时生成的信息(只写了部分)

触摸信息 含义
clientX / clientY 触摸点相对于浏览器的位置
pageX / pageY 触摸点相对于页面的位置
screenX / screenY 触摸点相对于屏幕的位置

总结:我们可以用触摸事件传入的参数event.changedTouches[0].pageX 获得我们触发( event )触摸事件那个手指( changedTouches[0] )当前位置相对于页面的位置( pageX )

二、轮播图实战

我们做的轮播图功能中只用到前三种触发事件,我们来看一下具体的应用。
因为vue.js项目中都是以组件的形式来开发的,所以我这里就以一个组件的形式来展示,有疑问的可以留言询问。

第一部分:template模板

<template>
    <div class="ContinuPlay_box" @touchstart="TouchStart" @touchmove="TouchMove" @touchend="TouchEnd">
      <div class="items_box">
        <div v-for="(item, index) in banners" class="slide" :key="index">
          <a :href="item.link" rel="external nofollow" >
            <img :src="item.image" alt="">
          </a>
        </div>
      </div>
      <div class="points_box">
        <div class="points">
          <div class="each_point" v-for="(item, index) in banners.length" :key="index" :class="{current:index==CurrentImg}"></div>
        </div>
      </div>
    </div>
</template>

第一部分解读:

1.class="ContinuPlay_box"的div标签作为组件模板里的根标签包裹内部标签(知识点:组件内如果多个标签处于同级,必须用一个标签将他们包裹起来),也用于设置overflow:hidden样式,用来隐藏未播放的轮播图

2.class="items_box"的div标签作为内部class=“slide” 的div标签的父标签,用来开启flex布局,该标签内主要内容就是轮播图图片

3.class=“slide” 的div标签用v-for指令对父组件传进来的数据banners进行遍历并输出

4.class="points"的div标签作为内部class="each_point"的div标签的父标签,用来开启flex布局,让轮播图的中下方的小圆点有序排列,该标签内部主要内容就是轮播图中间下方的进度条小圆点

第二部分:script标签内代码

<script>
  export default {
    name: "ContinuPlay",
    props:['banners'],         //接受父级组件传过来的banners数据
    data(){
      return{
        bannerwidth: 0,        //轮播图宽度
        StartPoint: 0,         //触摸开始的点的横坐标
        EndPoint: 0,           //触摸结束的点的横坐标
        MoveLength: 0,         //StartPoint与EndPoint的差值
        CurrentImg: 0,         //当前轮播图的索引
        isPlaying: true,       //判断是否处于自动轮播
        playTimer: null        //轮播定时器
      }
    },
    methods:{
      TouchStart(event){
      	//停止轮播
        clearInterval(this.playTimer)
        //获取触摸的开始点
        this.StartPoint = event.changedTouches[0].pageX
      },
      TouchMove(event){
        //获取触摸的结束点
        this.EndPoint = event.changedTouches[0].pageX
        this.slidings()
      },
      TouchEnd(){
        this.Jump()
        //开始轮播
        this.startPlay()
      },
      //Jump()方法用于处理滑动到一定程度后松手自动跳转到下一页或上一页
      Jump(){
        const currentimg = document.getElementsByClassName('slide')
        //滑动超过轮播图宽度的百分之40,则跳转下一张,否则不跳转
        if(this.MoveLength > 0 && this.CurrentImg !== this.banners.length-1){
          if(this.MoveLength > this.bannerwidth * 0.4){
            this.CurrentImg ++
            currentimg[0].style.marginLeft = -this.CurrentImg * this.bannerwidth + 'px'
          }
          else{
            currentimg[0].style.marginLeft = -this.CurrentImg * this.bannerwidth + 'px'
          }
        }
        else if(this.MoveLength < 0 && this.CurrentImg !== 0){
          if(-this.MoveLength > this.bannerwidth * 0.4){
            this.CurrentImg --
            currentimg[0].style.marginLeft = -this.CurrentImg * this.bannerwidth + 'px'
          }
          else{
            currentimg[0].style.marginLeft = -this.CurrentImg * this.bannerwidth + 'px'
          }
        }
      },
      //slidings()方法用于处理在滑动过程中,轮播图跟着手指滑动的距离移动
      slidings(){
        //判断是点击还是滑动
        if(this.StartPoint === this.EndPoint){return}
        this.MoveLength = this.StartPoint - this.EndPoint
        //操作DOM,获取轮播图对象标签
        const currentimg = document.getElementsByClassName('slide')
        //获取轮播图的宽度
        this.bannerwidth = currentimg[0].offsetWidth
        //判断是否超出滑动范围,即第一页无法再往前一页滑动,最后一页无法再往后一页滑动
        if(this.MoveLength > 0 && this.CurrentImg !== this.banners.length-1){
          currentimg[0].style.marginLeft = -this.MoveLength - this.CurrentImg * this.bannerwidth   + 'px'
        }
        else if(this.MoveLength < 0 && this.CurrentImg !== 0){
          currentimg[0].style.marginLeft = -this.MoveLength - this.CurrentImg * this.bannerwidth   + 'px'
        }
      },
      //开启轮播
      startPlay() {
          clearInterval(this.playTimer)
          this.playTimer = setInterval(() => {
            if(this.CurrentImg === 3) {
              this.CurrentImg = -1
            }
            this.CurrentImg ++
            const currentimg = document.getElementsByClassName('slide')
            this.bannerwidth = currentimg[0].offsetWidth
            currentimg[0].style.marginLeft = -this.CurrentImg * this.bannerwidth + 'px'
            currentimg[0].style.transition = 'all 1s ease'
          }, 3000)
      }
    },
    mounted() {
    	//页面挂在完毕自动开启轮播
    	this.startPlay()
    }
  }
</script>

第二部分解读:

1.在组件data属性中,初始化了几个变量:StartPoint(触摸开始点横坐标)、EndPoint(触摸结束时横坐标)、MoveLength(移动的长度(有正负))、CurrentImg(当前轮播图索引)

2.在页面挂在完成后, 触发methods中的startPlay方法,开启轮播功能

3.在触摸事件中主要运用 StartPoint - EndPoint 的值使得图片跟着手指的滑动方向同步移动, 并且在触摸开始时,关闭自动轮播定时器,在触摸结束后,自动开启轮播定时器

4.在松手后,通过Jump() 方法进行跳转上下页图片

第三部分:css样式部分

<style scoped>
  .ContinuPlay_box{
    overflow: hidden;
    position: relative;
  }
  .ContinuPlay_box .items_box{
    display: flex;
  }
  .ContinuPlay_box .slide{
    flex-shrink: 0;
    width: 100%;
  }
  .ContinuPlay_box .slide img, .ContinuPlay_box .slide a{
    width: 100%;
    height: 100%;
  }
  .points_box{
    display: flex;
    justify-content: center;
  }
  .points{
    display: flex;
    width: 33%;
    height: 10px;
    position: absolute;
    bottom: 8px;
    justify-content: space-evenly;
  }
  .points .each_point{
    width: 8px;
    height: 8px;
    border-radius: 8px;
    background: #fff;
    opacity: 0.7;
  }
  .points .current{
    background: #ff0031;
  }
</style>

css样式就不做多解释了,因为这比较抽象,你们可以根据我的代码进行调试优化,我的应该也不是最好的

三、效果图

此gif图展示的是我现在已经开发的部分项目效果图,其中包括本文讲的轮播图功能

vue.js 使用原生js实现轮播图

结束语

这是我在vue.js实战项目开发第二天中遇到的问题,希望我遇到的问题能对大家有所帮助, 如果大家感兴趣,可以关注一波,每天跟大家分享一些问题和解决办法,大家也可以跟我分享一下你们的经验。

Vue.js 相关文章推荐
详解vue 组件注册
Nov 20 Vue.js
Vue通过阿里云oss的url连接直接下载文件并修改文件名的方法
Dec 25 Vue.js
vue实现简易的双向数据绑定
Dec 29 Vue.js
Vue中引入svg图标的两种方式
Jan 14 Vue.js
vue如何使用rem适配
Feb 06 Vue.js
vue前端和Django后端如何查询一定时间段内的数据
Feb 28 Vue.js
vue引入Excel表格插件的方法
Apr 28 Vue.js
Vue全局事件总线你了解吗
Feb 24 Vue.js
vue使用wavesurfer.js解决音频可视化播放问题
Apr 04 Vue.js
vue 把二维或多维数组转一维数组
Apr 24 Vue.js
使用vuex-persistedstate本地存储vuex
Apr 29 Vue.js
vue如何清除浏览器历史栈
May 25 Vue.js
如何vue使用el-table遍历循环表头和表体数据
vue 把二维或多维数组转一维数组
Apr 24 #Vue.js
Vue OpenLayer 为地图绘制风场效果
Apr 24 #Vue.js
vue二维数组循环嵌套方式 循环数组、循环嵌套数组
vue @click.native 绑定原生点击事件
Apr 22 #Vue.js
vue实现省市区联动 element-china-area-data插件
vue修饰符.capture和.self的区别
Apr 22 #Vue.js
You might like
php中$_SERVER[PHP_SELF] 和 $_SERVER[SCRIPT_NAME]之间的区别
2009/09/05 PHP
PHP按指定键值对二维数组进行排序的方法
2015/12/22 PHP
php使用glob函数遍历文件和目录详解
2016/09/23 PHP
利用php抓取蜘蛛爬虫痕迹的示例代码
2016/09/30 PHP
PHP实现的数独求解问题示例
2017/04/18 PHP
js 获取浏览器高度和宽度值(多浏览器)
2009/09/02 Javascript
改变javascript函数内部this指针指向的三种方法
2010/04/23 Javascript
jquery验证表单中的单选与多选实例
2013/08/18 Javascript
简单的代码实现jquery定时器
2013/11/17 Javascript
jquery fancybox ie6不显示关闭按钮的解决办法
2013/12/25 Javascript
js动态添加onclick事件可传参数与不传参数
2014/07/29 Javascript
js简单实现标签云效果实例
2015/08/06 Javascript
微信企业号开发之微信考勤Cookies的使用
2015/09/11 Javascript
JS实现网页上随滚动条滚动的层效果代码
2015/11/04 Javascript
使用jquery获取url以及jquery获取url参数的实现方法
2016/05/25 Javascript
三种带箭头提示框总结实例
2016/06/14 Javascript
Angularjs根据json文件动态生成路由状态的实现方法
2017/04/17 Javascript
uploader秒传图片到服务器完整代码
2017/04/22 Javascript
详解nodejs的express如何自动生成项目框架
2017/07/12 NodeJs
Vue数据双向绑定原理及简单实现方法
2018/05/18 Javascript
JavaScript事件冒泡与事件捕获实例分析
2018/08/01 Javascript
nuxt配置通过指定IP和端口访问的实现
2020/01/08 Javascript
python基础入门详解(文件输入/输出 内建类型 字典操作使用方法)
2013/12/08 Python
使用cx_freeze把python打包exe示例
2014/01/24 Python
python定时利用QQ邮件发送天气预报的实例
2017/11/17 Python
python去除扩展名的实例讲解
2018/04/23 Python
Python读取csv文件分隔符设置方法
2019/01/14 Python
Python mutiprocessing多线程池pool操作示例
2019/01/30 Python
python里运用私有属性和方法总结
2019/07/08 Python
python 实现非极大值抑制算法(Non-maximum suppression, NMS)
2020/10/15 Python
Kathmandu英国网站:新西兰户外运动品牌
2017/03/27 全球购物
美国浴缸、水槽和水龙头购物网站:Vintage Tub & Bath
2019/11/05 全球购物
中学实习教师自我鉴定
2013/12/12 职场文书
我的中国梦口号
2014/06/16 职场文书
班级团队活动方案
2014/08/14 职场文书
Pytorch DataLoader shuffle验证方式
2021/06/02 Python