从Web到移动端,简化UI事件管理





5.00/5 (2投票s)
一种非常简单的方法,可以在从桌面浏览器切换到移动浏览器时获得最佳用户体验。
引言
本文将介绍我开发的一个脚本,旨在简化在移动电话上查看网站时的性能提升。
背景
最近,在开发一个新项目时,我们都启动了手机并开始测试。 立即我们都注意到,通过在移动设备上触摸触发点击事件所需的时间量很大,并且显著降低了应用程序的可用性。 双击被识别为单击,第二次点击丢失了。
发生这种情况的原因是手机支持基于触摸的事件架构。 Ontouchstart
、ontouchend
和 ontouchmove
都是可以在标记中指定并在移动设备上使用的新的事件。 当这些事件添加到HTML中时,事件立即开始触发。
延迟是由于手机的浏览器会一直查找触摸事件到窗口对象,然后才会触发点击事件。 因此会出现延迟。
我们调查了许多解决方法。
显而易见的方法是同时指定触摸和点击事件。 但我们不希望重复,特别是我们不需要触摸事件带来的任何好处,例如多点触控和手势等。
我们研究了使用JS在加载时导航DOM并将所有点击事件重新分配给触摸事件。 只要您不在重新分配后修改DOM而不重新分配,这种方法有效。 但我认为这是一个开发风险,将来可能会导致问题。
最终,我们提出了以下脚本,该脚本跨浏览器兼容,并且假设您只想让一个编程好的点击网站在手机上更好地工作,它就像梦一样运行!
使用代码
以下是代码块,请参阅注释以了解其工作原理。
它适用于IE8+、Chrome、Safari Win & Mac、Firefox。
//This method returns true if the browser and device supports touch events
function touchDeviceTest() {
try {
document.createEvent("TouchEvent");
return true;
} catch (e) {
return false;
}
}
//A flag for if the touches have scrolled
var tchHasScrolled = false;
//The random number generated for this touch event
var tchRandomId = 0.0;
//The random number generated for the last touch event
var tchRandomLastId = 0.0;
//The temp y position for the current touch
var touchYTemp = 0;
//this is the document scroll event method
function onDocumentScroll(e) {
tchHasScrolled = true;
}
//this is the document click event method
function onDocumentClick(e) {
//If the touch down and touch up randoms are the different
//Then good event so continue
if (tchRandomId != tchRandomLastId) {
//set last to current
tchRandomLastId = tchRandomId;
//if touch device
if (touchDeviceTest()) {
//if target not an anchor
if (e.target.tagName != 'A') {
//stop normal behaviour
e.stopPropagation();
e.preventDefault();
}
}
}
}
//this is the document touch start method
function onDocumentTouchStart(e) {
//set has scrolled to false
tchHasScrolled = false;
//asssign a new random id
tchRandomId = new Date().getMilliseconds() + Math.random();
//store the touch y point
touchYTemp = e.touches[0].clientY;
}
//this is the document touch move method
function onDocumentTouchMove(e) {
//if touch has moved more than 10px set scrolled flag to true
var y = e.touches[0].clientY;
if (y > touchYTemp + 10 || y < touchYTemp - 10) {
tchHasScrolled = true;
}
}
//this is the document touch end method
function onDocumentTouchEnd(e) {
//if there is still a touch, manage the scrolling
if (e.touches[0]) {
var y = e.touches[0].clientY;
if (y > touchYTemp + 10 || y < touchYTemp - 10) {
tchHasScrolled = true;
}
}
//if the document hasn't scrolled
if (!tchHasScrolled) {
//get the event target
var target = e.target.parentNode;
//if the target has a click event
if (e.target.onclick) {
//call click event
e.target.onclick(e);
} else {
//else, loop through parent looking for click event
while (target != null) {
if (target.onclick) {
//call click event
target.onclick(e);
break;
}
target = target.parentNode;
}
}
}
}
//assign the methods to the events
if (!document.addEventListener) {
document.attachEvent('onclick', onDocumentClick);
document.attachEvent('onscroll', onDocumentScroll);
document.attachEvent('ontouchstart', onDocumentTouchStart);
document.attachEvent('ontouchmove', onDocumentTouchMove);
document.attachEvent('ontouchend', onDocumentTouchEnd);
} else {
document.addEventListener('click', onDocumentClick, true);
document.addEventListener('scroll', onDocumentScroll, true);
document.addEventListener('touchstart', onDocumentTouchStart, true);
document.addEventListener('touchmove', onDocumentTouchMove, true);
document.addEventListener('touchend', onDocumentTouchEnd, true);
}
本质上,我们使用窗口上的触摸事件和参数中的事件目标来拦截触摸事件,并在找到时执行点击事件。
关注点
虽然锚标签内的链接的执行未定义为onclick事件。 在点击事件的事件传播中调用 e.preventDefault
将阻止锚点工作。 这就是我专门为锚点添加排除项的原因。