写在前边
- 本文主要介绍如何实现滑动切换及遇到的问题,具体组件代码点这
- 如果你需要的是轮播图,这里有两个轮子react-slick、nuka-carousel
- 原生DOM操作,非React框架下也能使用
实现效果
我们想实现触摸切换无非是做以下三件事
- 监听触摸事件
- 判断用户当前操作是否是切换
- 进行页面切换
获取触摸事件
如果你不了解触摸事件可以先看触摸事件
要想监听触摸事件整个流程需要监听以下三个事件
let lists = document.getElementsByClassName('tabs-ul-li');//我们监听的元素
lists.addEventListener("touchstart", (e) => {
//e.targetTouches[0].pageX;
//e.targetTouches[0].pageY;
});
lists.addEventListener("touchmove", (e) => {
//e.targetTouches[0].pageX;
//e.targetTouches[0].pageY;
});
lists.addEventListener("touchend", (e) => {
//e.changedTouches[0].pageX;
//e.changedTouches[0].pageY;
});
这里使用clientX/clientY、pageX/pageY都没有问题,我们需要的是偏移量,另外touchend事件触发时touches和targetTouches都被归0,使用changedTouches获取用户离开位置(单一触点的情况归0)
判断用户当前操作是否是切换
区分横向切换纵向滚动
一次触摸事件只执行一种操作,比如在屏幕上画7会触发切换不会触发滚动的。
这里我们想在用户横向滑动时切换页面,纵向滑动时滚动页面,需要在touchmove事件第一次触发时就判断用户到底是想滚动还是切换。当X轴偏移量大于Y轴偏移量时执行切换操作,小于等于时执行滚动。
lists.addEventListener("touchmove", (e) => {
let disX = e.targetTouches[0].pageX - this.initPageX;
let disY = e.targetTouches[0].pageY - this.initPageY;
if (Math.abs(disX) - Math.abs(disY) > 0) {
this.touchEvent = 'switch';
} else {
this.touchEvent = 'scroll'
}
});
滑动是touchmove的默认事件,所以在一次触摸操作被确定为切换时要取消touchmove的默认事件。
lists.addEventListener("touchmove", (e) => {
e.preventDefault();
}, {
passive: false// 禁止 passive 效果
});
这里不写 passive: false在某些浏览器无法实现禁止默认事件,原因看这里
区分同向不同组件切换
使用targetTouches就是为了区别不同组件的同向切换事件,当然这是指组件没有共同区域的情况。如果不同切换事件有共同区域,我们也可以通过设置优先级来保证一次触摸操作只执行一个操作。
进行页面切换
切换时要考虑切换的方向
lists.addEventListener("touchend", (e) => {
let switchDirection = '';
//在手指离开手机后touches和targetTouches中对应的元素会同时移除
if (e.changedTouches[0].pageX - this.initPageX > 0) {
switchDirection = 'left'
} else if (e.changedTouches[0].pageX - this.initPageX < 0) {
switchDirection = 'right'
}
});