移动端触摸分页方案
-
场景:移动端列表显示,数据庞大。后台数据有分页字段
-
需求:需要快速显示页面,需要显示当前页数,需要跨页跳转
Pc端可以使用分页按钮,但是移动端屏幕小,分页按钮不方便操作。思路分析
- 思路1:下拉刷新实现分页加载
可以使用iscroll插件进行下拉刷新,符合用户使用习惯。但是无法进行跨页跳转,也无法显示当前页码 - 思路2:使用搜索功能,查找想要的数据。
参考了淘宝对商品的筛选功能,用户可以选择筛选条件进行查询。实用性强,但实现步骤较为繁琐 - 思路3:使用滑块快速跳转页码
这种方式最符合需求,查找了资料,可以使用UIsilder组件,但是样式不太美观,与产品界面风格不符。
经过讨论和初步实践,决定选取第3种方案,但不采取slider组件,参考某些阅读器的分页样式,也可以参考微信通讯录的滑动实现。
类似效果图
image具体实操
html和css部分
//页码部分
<div id="sliderPage">
<div id="wrap" ></div>
</div>
//放大显示页码标签
<div class="largePage" >
<span>1</span>
</div>
设置样式让页面如图显示
js部分
滑动跳转,滑动在于Js部分的动作交互,跳转在于数据接口的调用。
1.滑动
这部分主要使用了touch系列事件,在页面dom上添加touch事件。我这里直接加在了html节点上。
<div id="sliderPage" ontouchend="touchEnd()" ontouchmove="move()"></div>
重点代码
根据数据创建页码
function createPage(){
...
//pageCount为页码数。
//total为数据总数,这里每页显示10条。
var pageCount = parseInt((total+ (10 - 1)) / 10);
var str;
for(let i = i;i <= pageCount+1;i++){
str +='<a ontouchstrat=start(this) >'+i+'</a>'
}
$("wrap").html(str);
}
#### touchstart事件获取当前页码,并将页码显示在largepage下的标签中
function start(n){
var text= (.largePage span).text(text);
$(".largePage span").css("opacity","1")
}
#### touchmove滑动事件
function move(){
//滑动切换页码
//将页码显示在
//根据start对象的宽高进行切换
start(document.elementFromPoint(event.changedTouches[0].clientX, event.changedTouches[0].clientY))
}
#### touchend滑动结束,页码提示隐藏,跳转页面
function touchEnd(){
$(".largePage").animate({
opacity:0
},500)
//页面跳转操作
}
现象分析
功能逻辑不复杂,但是涉及到了touch系列事件的操作。页面如果存在一些click事件或者其他的touch事件,就会出现各种问题。
对click事件的影响。
touch事件结束后会触发节点的click事件
在移动端,手指点击一个元素,会经过:touchstart --> touchmove -> touchend -->click
事件流本身会持续进行下去。
touchstart
触发之后,click
事件还被触发了,onclick
属性也被触发了。
使用preventDefault()
方法可以阻止click事件被触发。
event.preventDefault()
表示取消默认事件,比如可以禁止touchmove事件触发时页面滚动。一般情况都要加上,否则会出现很多怪异现象
事件冒泡
页面document也有touchmove和end事件,用于显示和隐藏页码条。
//触发touchmove事件显示页码条
document.addEventListener("touchmove",function(){
$("#sliderPage").animate({
opacity:1
},500)
},false);
//触发touchend事件隐藏页码条
document.addEventListener("touchend",function(){
$("#sliderPage").animate({
opacity:0
},2000)
},false)
这么写在sliderPage上滑动的时候也会触发这两个事件,造成sliderPage不稳定时隐时现。所以要关闭touch事件的冒泡行为
//在所有的Touch事件中加上这一句
event.stopPropagation();
不过我采取了另外一种方式。使用监听滚动条变化来显示和隐藏页码条,也就没有这个问题了.
//页面滚动时,显示页码条
$(window).on('scroll', function() {
$("#sliderPage").animate({
opacity:1
},500);
//设置延时,隐藏页码条
setInterval(function(){
$("#sliderPage").animate({
opacity:0
},2000);
},3000)
})
#### touch事件拓展
touch事件都会冒泡,也都可以取消。虽然这些触摸事件没有在DOM规范中定义,但是它们却是以兼容DOM的方式实现的。所以,每个触摸事件的event对象都提供了在鼠标实践中常见的属性:
* bubbles(起泡事件的类型)
* cancelable(是否用 preventDefault() 方法可以取消与事件关联的默认动作)
* clientX(返回当事件被触发时,鼠标指针的水平坐标)
* clientY(返回当事件触发时,鼠标指针的垂直坐标)
* screenX(当某个事件被触发时,鼠标指针的水平坐标)
* screenY(返回当某个事件被触发时,鼠标指针的垂直坐标)
touch对象代表一个触点,可以通过event.touches[0]获取
除了常见的DOM属性,触摸事件还包含下面三个用于跟踪触摸的属性
* touches:表示当前跟踪的触摸操作的touch对象的数组。
* targetTouches:特定于事件目标的Touch对象的数组。
* changeTouches:表示自上次触摸以来发生了什么改变的Touch对象的数组。
每个Touch对象包含的属性如下。
* identifier:标识触摸的唯一ID。
* clientX:触摸目标在`视口`中的x坐标。
* pageX:触摸目标在`页面`中的x坐标
* screenX:触摸目标在`屏幕`中的x坐标。
* target:触摸的DOM节点目标。
* ex:
function load (){
document.addEventListener('touchstart',touch, false);
document.addEventListener('touchmove',touch, false);
document.addEventListener('touchend',touch, false);
}
function touch (event){
var event = event || window.event;
var oInp = document.getElementById("inp");
switch(event.type){
case "touchstart":
oInp.innerHTML = "Touch started (" + event.touches[0].clientX + "," + event.touches[0].clientY + ")";
break;
case "touchend":
oInp.innerHTML = "<br>Touch end (" + event.changedTouches[0].clientX + "," + event.changedTouches[0].clientY + ")";
break;
case "touchmove":
event.preventDefault();
oInp.innerHTML = "<br>Touch moved (" + event.touches[0].clientX + "," + event.touches[0].clientY + ")";
break;
}
}
window.addEventListener('load',load, false);