65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2014年1月2日

CPOL

2分钟阅读

viewsIcon

11299

一种非常简单的方法,可以在从桌面浏览器切换到移动浏览器时获得最佳用户体验。

引言

本文将介绍我开发的一个脚本,旨在简化在移动电话上查看网站时的性能提升。

背景 

最近,在开发一个新项目时,我们都启动了手机并开始测试。 立即我们都注意到,通过在移动设备上触摸触发点击事件所需的时间量很大,并且显著降低了应用程序的可用性。 双击被识别为单击,第二次点击丢失了。

发生这种情况的原因是手机支持基于触摸的事件架构。 Ontouchstartontouchend 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 将阻止锚点工作。 这就是我专门为锚点添加排除项的原因。

© . All rights reserved.