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 24 Vue.js
element-plus一个vue3.xUI框架(element-ui的3.x 版初体验)
Dec 02 Vue.js
vue3.0实现插件封装
Dec 14 Vue.js
基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能
Jan 05 Vue.js
vue浏览器返回监听的具体步骤
Feb 03 Vue.js
用vite搭建vue3应用的实现方法
Feb 22 Vue.js
vue实现滑动解锁功能
Mar 03 Vue.js
三种方式清除vue路由跳转router-link的历史记录
Apr 10 Vue.js
vue打包时去掉所有的console.log
Apr 10 Vue.js
vue使用localStorage持久性存储实现评论列表
Apr 14 Vue.js
vue3种table表格选项个数的控制方法
Apr 14 Vue.js
vue 给数组添加新对象并赋值
Apr 20 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调用数据库的存贮过程!
2006/10/09 PHP
php的memcached客户端memcached
2011/06/14 PHP
浅析php学习的路线图
2013/07/10 PHP
PHP FATAL ERROR: CALL TO UNDEFINED FUNCTION BCMUL()解决办法
2014/05/04 PHP
javascript 去字符串空格终极版(支持utf8)
2009/11/14 Javascript
js如何设置在iframe框架中指定div不显示
2013/12/04 Javascript
JS过滤url参数特殊字符的实现方法
2013/12/24 Javascript
node.js中的Socket.IO使用实例
2014/11/04 Javascript
JS判断form内所有表单是否为空的简单实例
2016/09/09 Javascript
EditPlus 正则表达式 实战(3)
2016/12/15 Javascript
Angular @HostBinding()和@HostListener()用法
2018/03/05 Javascript
详解Webpack + ES6 最新环境搭建与配置
2018/06/04 Javascript
Angular4.x Event (DOM事件和自定义事件详解)
2018/10/09 Javascript
详解BootStrap表单验证中重置BootStrap-select验证提示不清除的坑
2019/09/17 Javascript
Python+tkinter使用80行代码实现一个计算器实例
2018/01/16 Python
Python+Turtle动态绘制一棵树实例分享
2018/01/16 Python
pandas读取CSV文件时查看修改各列的数据类型格式
2019/07/07 Python
Python sqlite3查询操作过程解析
2020/02/20 Python
使用keras2.0 将Merge层改为函数式
2020/05/23 Python
keras 使用Lambda 快速新建层 添加多个参数操作
2020/06/10 Python
PyTorch中Tensor的数据类型和运算的使用
2020/09/03 Python
Django配置Bootstrap, js实现过程详解
2020/10/13 Python
UI自动化定位常用实现方法代码示例
2020/10/27 Python
移动端html5模拟长按事件的实现方法
2018/09/30 HTML / CSS
贝玲妃英国官网:Benefit英国
2018/02/03 全球购物
西铁城美国官方网站:Citizen Watch美国
2019/11/08 全球购物
Trench London官方网站:高级风衣和意大利皮夹克
2020/07/11 全球购物
递归实现回文判断(如:abcdedbca就是回文,判断一个面试者对递归理解的简单程序)
2013/04/28 面试题
幼儿园教师演讲稿
2014/05/06 职场文书
平安家庭示范户事迹
2014/06/02 职场文书
道歉信范文
2015/05/12 职场文书
物业保安辞职信
2015/05/12 职场文书
社区挂职锻炼个人工作总结
2015/10/23 职场文书
vue3中的组件间通信
2021/03/31 Vue.js
Golang的继承模拟实例
2021/06/30 Golang
JavaScript实例 ODO List分析
2022/01/22 Javascript