mui提供了tap事件替換了html5的click事件,解決了300ms延時的問題。不過相比原生app的click體驗還是有些許差距的。關於300ms延時的問題,這篇帖子分析的比較完善,其中提到了穿透的問題,值得一讀
僅用微信為例,只有當手指離開屏幕時才觸發click事件,如果對象綁定了長按事件,則觸發長按操作,離開時不再觸發單擊事件。
這些邏輯無論是android, ios或者僅有1%的windows mobile都已經封裝好了,根本不用關心。
那么,我們應該怎么來實現呢?
下面是詳細的填坑歷程。。。。。。
坑1.通過原生的touch來實現
//直接對dom添加touchend,這種方法只能針對位置不變且並沒有添加longtap事件的DOM有效
//如果在listview中,你上下滑動,那就歇菜了。
//那么自然而然就想到了touch.target的位移,並做出判斷是下滑還是單擊。
//自己去寫復雜度、代碼量估計會很可觀。
//因此就想到了了在原有的框架代碼上去實現。
//下面就到了坑2
document.getElementById("").('touchend', function() {
//
});
坑2.更改mui.gestures.tap.js
坑2.1 自定義事件偵聽機制
mui沒有提供類似於jq.data('events')獲取事件列表的機制,另外官方也推薦使用addEventListener
去綁定事件。
我要去獲取當前DOM的事件列表應該怎么做呢?
你問我問毛要去獲取DOM的事件列表,,,
呵呵,我總要知道DOM有木有綁定longtap事件好做規避吧
csdn的這個帖子看似有用
http://bbs.csdn.net/topics/390250552
function addEvent(dom,type,fn) {
if(document.addEventListener) {
dom.addEventListener(type, fn, false);
} else if(document.attachEvent) {
dom.attachEvent('on' + type, fn);
} else {
dom['on' + type] = fn;
};
dom["Listener-"+type]=!0;
}
實際上並沒有什么卵用
思想是好的.....
我總不能每次addEventListener都去調一下這個方法吧!
坑2.2 使用getEventListeners
找啊找,終於找到了getEventListeners()
這個全局方法,在chrome和safari控制台中測試都木有問題。
喜出望外......
這下終於能解決問題了
於是有了以下的方法
var getEvents = function(obj) {
console.log(getEventListeners(obj));
return typeof(getEventListeners) == "function" && getEventListeners(obj);
}
var hasEventype = function(obj, e) {
var es = getEvents(obj);
console.log(es[e]);
return es && !!es[e];
}
調用下試試
if (!hasEventype(target, 'longtap')) {}
報錯
getEventListeners
is undefined
R U kidding?!!!!
你丫在逗我.............
我瞬間感受到了深深地惡意
原來這個方法只能在控制台中用,
呵呵,人艱不拆......
坑2.3 使用全局變量規避
給mui添加一個全局變量isLongTapAtived
,看變量名就知道什么意思吧
在mui.gestures.longtap.js
中初始化,在handle
中激活
(function($, name) {
$.isLongTapAtived = false;//初始化
var timer;
var handle = function(event, touch) {
switch (event.type) {
case $.EVENT_START:
clearTimeout(timer);
timer = setTimeout(function() {
$.trigger(session.target, name, touch);
//激活了
$.isLongTapAtived = true;
}, options.holdTimeout);
break;
}
};
});
})(mui, 'longtap');
在mui.gestures.tap.js
中判斷有無激活
var handle = function(event, touch) {
var session = $.gestures.session;
var options = this.options;
switch (event.type) {
case $.EVENT_END:
//......
if (touch.distance < options.tapMaxDistance) {
if (touch.deltaTime < options.tapMaxTime) {
//.....
} else {
//如果當前對象添加了長按偵聽,略過,否則仍然視為tap事件
//if (!hasEventype(target, 'longtap')) {
if (!$.isLongTapAtived) {
//如果沒有longtap事件,離開屏幕是觸發tap事件
$.trigger(target, name, touch);
}
//重置
$.isLongTapAtived = false;
}
}
break;
}
};
想法是美好的,現實是他么殘酷的。無論有無longtap
事件,都要走一遍longtap
的handle
代碼
於是 $.isLongTapAtived === true;
於是 永遠trigger
tap
事件
呵呵,想死的心都有了
路子看來是走對了,但是應該怎么做???
終極解決方案
mui.isLongTapAtived
依然添加,只是在每一次DOM添加的longtap事件內激活
document.querySelector("#").addEventListener('longtap',function(){
mui.isLongTapAtived=true;
console.log('你觸發了longtap事件');
});
這樣對開發者是不友好的,不過暫時沒辦法,只能如此取舍了
代碼已提交至https://github.com/phillyx/mui/
並推送給官方