1、问题描述
上述手机出现无法滑动或者无法触发点击事件的情况
2、问题分析
1、onBeforeScrollStart方法
onBeforeScrollStart: function (e) { e.preventDefault(); }
此方法是在_start里进行了调用,目的是为了阻止浏览器默认动作的执行,防止在
滑动的过程中进行干扰,同时也就阻止了滑动区域里元素的事件的触发,这种处
理方式也直接导致了必须要在_end方法中再次触发元素的点击事件
2、_end方法
if (target.tagName != 'SELECT' && target.tagName != 'INPUT'
&& target.tagName != 'TEXTAREA') {
ev = document.createEvent('MouseEvents');
ev.initMouseEvent('click', true, true,
e.view, 1,point.screenX,
point.screenY, point.clientX,
point.clientY,e.ctrlKey,
e.altKey, e.shiftKey,
e.metaKey,0, null);
ev._fake = true;
target.dispatchEvent(ev);
}
这个处理方式就是顺承了上面所提到的阻止了浏览器默认行为后,对滑动区域
除SELECT、INPUT、TEXTAREA外的元素触发click事件,已完成对click绑定事件的调用
【具体分析】
由于onBeforeScrollStart是在_start方法中进行的调用,e.preventDefault();阻止了元
素的默认行为,从而导致了元素绑定事件的失效,必须在_end操作结束后进行
绑定事件的模拟调用,原始的iScroll源代码中在_end中最后创建了click事件的
模拟,但是这里必须要清楚的一个原理就是,click其实是要依赖于其他事件的:
1) 普通pc网页中,click需要依赖于mousedown、mouseup的相继触发
2) 移动webkit中,click则需要依赖于touchstart、touchend
(实际mousedown,mouseup在移动webkit上也存在)的相继触发
“相继触发”的意思就是中间不会夹杂有其他的事件类型,这也就很容易理解
iScroll中在_end中对模拟事件调用的条件了,必须要判断that.moved才能直接触
发模拟事件。iScroll中与_start、_move、_end相关的三个事件类型是按照如
下的规则来设置的:
START_EV = hasTouch ? 'touchstart' : 'mousedown'
MOVE_EV = hasTouch ? 'touchmove' : 'mousemove'
END_EV = hasTouch ? 'touchend' : 'mouseup'
【注意事项】
经测试,三星部分手机里默认浏览器里会默认所有元素都有一个默认的click
事件(测试结果显示鼠标事件中默认事件包含mouseup,mousedown,click,
dblclick在移动webkit上不支持,为系统放大功能),e.preventDefault时会阻止
掉默认click事件的执行,必须要人为的在_end结束之后模拟click事件的调用,
而其他正常手机即使调用了e.preventDefault也不会阻止click事件的触发,因为
这些手机的默认浏览器上的元素的click事件的cancelable属性不为true,不可
以被preventDefault取消掉,会正常执行,而如果在_end中模拟了click事件则
将会导致click的重复调用(在有toggle状态的事件上非常明显),因此折中
的方式参见下面的解决方案。
3、解决方案
1. 去除onBeforeScrollStart里的阻止默认行为
onBeforeScrollStart: function (e) { //e.preventDefault(); }
2. onBeforeScrollMove设置为
function (e) {e.preventDefault();}
以保证手机上的正常滑动免受浏览器默认行为影响(如下滑时会有窗口的scroll事件),
当然如果这里不添加的话也可以在document的END_EV中阻止浏览器默认行为
3. _end 中将模拟事件名更改为END_EV或者直接去掉模拟事件的功能(注释掉如下部分):
// that.doubleTapTimer = setTimeout(function () {
// that.doubleTapTimer = null;
//
// // Find the last touched element
// target = point.target;
// while (target.nodeType != 1) target = target.parentNode;
//
// if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') {
// ev = doc.createEvent('MouseEvents');
// ev.initMouseEvent('click', true, true, e.view, 1,
// point.screenX, point.screenY, point.clientX, point.clientY,
// e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
// 0, null);
// ev._fake = true;
// target.dispatchEvent(ev);
// }
// }, that.options.zoom ? 250 : 0);
二、 鼠标滚轮滚动太慢