vue.js项目中用原生js实现移动端的轮播图_接口实现vue.js轮播图_「零一」的博客-程序员秘密

技术标签: vue  js  vue.js  html  javascript  

前言

今天我在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">
            <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图展示的是我现在已经开发的部分项目效果图,其中包括本文讲的轮播图功能
在这里插入图片描述

结束语

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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/l_ppp/article/details/105883664

智能推荐

Linux打包命令详解_drefong的博客-程序员秘密

tar命令[[email protected] ~]# tar [-cxtzjvfpPN] 文件与目录 ....参数:-c :建立一个压缩文件的参数指令(create 的意思);-x :解开一个压缩文件的参数指令!-t :查看 tarfile 里面的文件

在STM32中使用DSP库_linuxweiyh的博客-程序员秘密

软件环境:STM32CubeMX、Keil5硬件环境:STM32F4071.使用STM32CubeMX生成Keil5工程注意:点击Project -&amp;gt; Settings打开工程设置窗口,点击Code Generator选项卡,在STM32Cube Firmware Library Package中选择Copy all used libraries into the project ...

以下程序段实现“字符串变形拷贝”,将源字符串拷贝到目标字符串,并且 将其中的小写字母转换成大写字母,而其它字符保持不变。填写空缺的代码。 要求:不使用string.h中的函数。_Ly_deboke的博客-程序员秘密

代码为:#include &lt;stdio.h&gt;void transCopy(char *dst, const char* src){ // 变形拷贝函数 for( ;*src!='\0';src++,dst++) *dst = *src&gt;='a'&amp;&amp;*src&lt;='z' ? *src-32 : *src; *dst...

A-KAZE论文研读_ldb描述子_zcg1942的博客-程序员秘密

AKAZE是KAZE的加速版本。KAZE在构建非线性空间的过程中很耗时,在AKAZE中将Fast Explicit Diffusion(FED)加入到金字塔框架可以dramatically speed-up。在描述子方面,AKAZE使用了更高效的Modified Local Difference Binary(M-LDB),可以从非线性空间中利用梯度信息gradient information。M...

ubuntu 文件管理器推荐_nachifur的博客-程序员秘密

推荐xfce4自带的文件管理器(速度很快):sudo apt install thunarubuntu自带的:sudo apt install nautilusdeepin自带的:sudo apt install dde-file-manager

java毕业生设计校园疫情信息管理系统计算机源码+系统+mysql+调试部署+lw_你眼里的星星的博客-程序员秘密

java毕业生设计校园疫情信息管理系统计算机源码+系统+mysql+调试部署+lw。springboot基于B_S架构的疫情包联信息管理系统的设计与实现。springboot基于springboot和vue的酒店管理系统。springboot基于springboot+vue的线上学习系统。springboot基于springboot的社会公益平台。JSP客户关系管理系统的设计与实现sqlserver。springboot基于web的学校工资管理系统。springboot衣橱系统的设计与实现。

随便推点

一维、二维动态数组(vector)的创建_vector创建一维数组_CT_WJ的博客-程序员秘密

概念数组是一种基本的数据结构,用于按顺序存储元素的集合。但是元素可以随机存取,因为数组中的每个元素都可以通过数组索引来识别。数组具有固定的容量,我们需要在初始化时指定数组的大小。有时它会非常不方便并可能造成浪费。因此,大多数编程语言都提供内置的动态数组,它仍然是一个随机存取的列表数据结构,但大小是可变的。例如,在 C++ 中的 vector,以及在 Java 中的 ArrayList。一维数组...

DW1000FOLLOWER开发版简介_工程人在路上的博客-程序员秘密

淘宝链接:https://item.taobao.com/item.htm?id=543783701386&scm=1007.11461.75999.0&pvid=04e96f17-666f-4e9f-979f-bf92682aeee1&scm=1007.11461.75999.0&pvid=04e96f17-666f-4e9f-979f-bf92682aeee1DW1000FOLLO

Run-Time Check Failure #0,The value of ESP was not properly saved_孤独的泪的博客-程序员秘密

调用DLL函数,出现错误Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a f

机器学习笔记——正则化、欠拟合与过拟合_Simp丶的博客-程序员秘密

欠拟合(underfitting)高偏差(high bias),曲线不能很好的拟合训练数据。过拟合(overfitting)高方差(high variance),通常因为过多的特征导致,曲线能够很准确的拟合训练数据,但是不能泛化到新的数据。解决过拟合问题的方法减少特征变量数目 人工选择保留的特征、模型选择算法正则化 保留所有特征,但降低θjθj...

自动化接口测试平台,源码,自动化接口平台,可视化在线编写管理接口测试用例,批量生成用例_「已注销」的博客-程序员秘密

自动化接口测试平台,源码,自动化接口平台(比自动化框架更高一级)可视化在线编写管理接口测试用例,批量生成用例两种美观的测试报告,报告有导出成excel功能,导入用例功能定时执行用例功能,账号数据权限独立,有提供写函数的文件,完全满足接口测试的需求,python3+djiango+js+mysql+rabbitmq...

捡了个美男,该卖多少钱?_闲言长语的博客-程序员秘密

文 | 十里菱歌01.我在战事刚毕的沙场上,捡到了一头狮子和一个男人。四面风声寂寥,亘古月光惨白地洒下,被烽火灼出了黑洞的战旗倒在血沙里,我一边念着“南无阿尼陀佛”一边打着哆嗦蹲在地上捣鼓。自古以来,最残忍的事情莫过于两件,一件是马革裹尸,一件是没钱吃饭。男人是第一件我是第二件,我感觉自己和他同病相怜。狮子奄奄一息地倒在这名男子身旁,男子双目紧闭,面色雪白如霜,脸上寻不着一

推荐文章

热门文章

相关标签