vue.js项目中用原生js实现移动端的轮播图
Vue.js项目中封装轮播图组件前言一、了解原生js移动端的事件前言今天我在vue.js项目实战开发过程中遇到了实现轮播图效果的问题,因为不想因为一个轮播图而引用整个jquery,而且我还发现自己根本就不清楚移动端的一些事件,所以我就进行了一些资料查找,并最终解决了这个问题,接下来跟大家分享一下我的解决问题的过程.一、了解原生js移动端的事件原生...
Vue.js项目中封装轮播图组件
前言
今天我在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>
第一部分解读:
- class="ContinuPlay_box"的div标签作为组件模板里的根标签包裹内部标签(知识点:组件内如果多个标签处于同级,必须用一个标签将他们包裹起来),也用于设置overflow:hidden样式,用来隐藏未播放的轮播图
- class="items_box"的div标签作为内部class=“slide” 的div标签的父标签,用来开启flex布局,该标签内主要内容就是轮播图图片
- class=“slide” 的div标签用v-for指令对父组件传进来的数据banners进行遍历并输出
- 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>
第二部分解读:
- 在组件data属性中,初始化了几个变量:StartPoint(触摸开始点横坐标)、EndPoint(触摸结束时横坐标)、MoveLength(移动的长度(有正负))、CurrentImg(当前轮播图索引)
- 在页面挂在完成后, 触发methods中的startPlay方法,开启轮播功能
- 在触摸事件中主要运用 StartPoint - EndPoint 的值使得图片跟着手指的滑动方向同步移动, 并且在触摸开始时,关闭自动轮播定时器,在触摸结束后,自动开启轮播定时器
- 在松手后,通过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实战项目开发第二天中遇到的问题,希望我遇到的问题能对大家有所帮助, 如果大家感兴趣,可以关注一波,每天跟大家分享一些问题和解决办法,大家也可以跟我分享一下你们的经验。
更多推荐
所有评论(0)