最近剛作完一個移動端的項目,產品之無敵,過程之艱辛,我就很少說了,記錄下在這個項目中遇到的問題,以防萬一,雖然這些可能都是已經被N多前輩解決掉了的問題,也放在這裏,算是爲本身漫漫前端路鋪了一顆小石子兒吧,也在文末留下本身未能解決的疑問,但願看到的朋友能解惑。javascript
都知道作移動端的開發,在電腦上調試好了的東西,放在手機裏可能真的秒秒鐘就炸了,我發誓絕對沒想到炸的這麼快。。。css
這個小標題好像不太明確,大概就是,APP中有一個列表顯示的頁面,頁面上有個搜索功能,使用keyup監聽input框,每一次keyup都去檢索一下緩存數據有沒有符合的數據,然而、然鵝,IOS上並無能在每一次keyup都去檢索,通過各類查發現,IOS的輸入法(不論是第三方仍是自帶)能檢測到英文或者數字的keyup,檢測不到中文的keyup,(至於標點那些,就沒有深究了),在輸入中文以後須要點擊回退按鍵,纔會開始搜索,我本身能想到的辦法就是定時檢測setInterval,我也只能想到這辦法了,可是總以爲不太好,因而搜索到了這個辦法(http://blog.csdn.net/lytlx/article/details/50845259), 把keyup事件換成「input」和「propertychange」事件。html
oninput 是 HTML5 的標準事件,對於檢測 textarea, input:text, input:password 和 input:search 這幾個元素經過用戶界面發生的內容變化很是有用,在內容修改後當即被觸發,不像 onchange 事件須要失去焦點才觸發。oninput 事件在主流瀏覽器的兼容狀況以下:前端
oninput 事件在 IE9 如下版本不支持,須要使用 IE 特有的 onpropertychange 事件替代,這個事件在用戶界面改變或者使用腳本直接修改內容兩種狀況下都會觸發,有如下幾種狀況:java
在監聽到 onpropertychange 事件後,可使用 event 的 propertyName 屬性來獲取發生變化的屬性名稱,這樣看來,oninput & onpropertychange 彷佛是監聽輸入框值變化的最佳方案。node
原來的代碼:web
$(".ui-searchbar-input input").keyup(function () {
////
});瀏覽器
修改後的代碼:緩存
$(".ui-searchbar-input input").bind("input", function () {網絡
////
});
這樣一改以後,IOS也能正常啦~~~~
頁面上有個水滴狀的圖片,要求水平拖動修改餘額顯示,天然而然想到的就是用touchstart、touchmove、touchend來搞定了,因爲是初次使用,免不得會偷懶,從網上找了一些使用代碼來縫縫補補,改爲本身想要的效果,如下是初始代碼,也就是致使頁面不能滑動的罪魁禍首:
$("#img-balance").on("touchstart", function (e) {
var touches = e.touches[0];
oW = touches.clientX - $(this).offset().left;
oH = touches.clientY - $(this).offset().left;
$(document).on("touchmove", function (event) {
event.preventDefault();
}, false);
});
$("#img-balance").on("touchmove",function(e){
var touches = e.touches[0],
oLeft = touches.clientX - oW;
if (oLeft < 20) {
oLeft = 20;
} else if (oLeft > document.documentElement.clientWidth - 45) {
oLeft = document.documentElement.clientWidth - 45;
}
$(this).css("left", oLeft + "px");
mainModule.showBalance(0);
});
$("#img-balance").on("touchend",function(){
$(document).off("touchmove", function (event) {
event.preventDefault();
}, false);
});
以上代碼能完成我想要的效果,在電腦上玩兒的好好的,結果放在手機上就跪了,原來能夠上下滑動的頁面,只要一滑動圖片,頁面就不能上下滑動了,再檢查了一下代碼,表示徹底不清楚爲何要在touchstart和touchend裏面綁touchmove事件,這可能也是拷別人代碼的弊端吧,由於不知道緣由,索性就把那兩段代碼給刪了,結果頁面莫名其妙的就滿血復活了,如下是修改後的代碼:
$("#img-balance").on("touchstart", function (e) {
var touches = e.touches[0];
oW = touches.clientX - $(this).offset().left;
});
$("#img-balance").on("touchmove",function(e){
var touches = e.touches[0],
oLeft = touches.clientX - oW;
if (oLeft < 2) {
oLeft = 2;
} else if (oLeft > document.documentElement.clientWidth - 35) {
oLeft = document.documentElement.clientWidth - 35;
}
$(this).css("left", oLeft + "px");
mainModule.showBalance(0);
});
由於刪掉off代碼以後touchend裏面幾乎沒有東西了,索性就把touchend也刪了,發現並不影響效果,就偷着樂了,後經查證發現,頁面不能滑動,就是由於那個event.preventDefault()阻止了事件的默認行爲(頁面滑動???),因此,把它刪掉就行了。
頁面中的滑動刷新使用的是iscroll,鬱悶的是我周邊的全部人的手機滑起來都是順暢的不要不要的,只有個人,徹底劃不動,卡得抓狂,鑑於只有個人手機有這個問題,因此我把它放在了項目的最後來解決,甚至抱着只有我一個覆蓋率或許能夠不修復這個問題的小僥倖,如今想一想真是慚愧(主要是我旁邊的大牛說,「你要知道有一個你,就有千千萬萬個你」,你贏了)。
在網上查的時候發現還真是有千千萬萬個我,發現不少人都遇到過這個問題,其中有我以爲可信度較高的知乎(https://www.zhihu.com/question/21938954)、CSDN(http://blog.csdn.net/bbsyi/article/details/50915049 ,http://blog.csdn.net/ml01010736/article/details/50999335)等,還有一些不知名網站,都給出評論說可行的解決方案,無外乎就是如下幾種(可能是知乎總結出來的):
1) iScroll v5.1.3 momentum: true (我用的iscroll的版本沒這麼高,因此就沒有試過這種方法,不知是否可行)
2) 關閉probeType屬性 (傳說是由於這個啓用監聽滾動狀態的很耗性能,關閉這個屬性滑動就會流暢不少)
3)給scroll元素增長css樣式:-webkit-transform:translate3d(0,0,0);
以上3種方式,我試事後兩種,項目中的iscroll初始化爲:
_myScroll = new IScroll('#wrapper', {
probeType: 3,
mouseWheel: true,
click: true
});
wrapper中的DOM爲:
<div id="wrapper">
<div id="scroller">
<div id="scroller-pullDown">
<span id="down-icon" class="icon-double-angle-down pull-down-icon"></span>
<span id="pullDown-msg" class="pull-down-msg">下拉刷新</span>
</div>
<div id="scroller-content">
<div class="div-list">
</div>
</div>
<div id="scroller-pullUp">
<span id="up-icon" class="icon-double-angle-up pull-up-icon"></span>
<span id="pullUp-msg" class="pull-up-msg">上拉刷新</span>
</div>
</div>
</div>
先是第三種,給scroll元素增長css樣式,scroll元素是#scroller,上午作測試的時候用的是#scroller-content(啊啊啊啊啊!!!)如今才發現元素選錯了,不知道是否是這個緣由致使的第三種方法沒有生效(存疑)。
第二種方法,註釋掉實例化時的probeType屬性,然而發現,並無什麼用。。。因而又開啓了茫茫網絡上的撈針行動。
最終,在CSDN(http://blog.csdn.net/ml01010736/article/details/50999335)上找到了可行辦法:
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
偶,這中間還有個小插曲,爲了解決這個滑動問題,一度傻逼得懷疑是否是沒有寫fastclick的緣由,後來加上了並無解決問題,也忘記了刪掉,還致使後面的a標籤須要點擊屢次才能跳轉連接的問題,鬱悶。。。
加上了這句代碼以後,個人手機頁面終於也是順順暢暢的了,哈~舒心~就喜歡遇到這種花時間就能解決的問題。
因爲iscroll要監聽鼠標事件和觸摸事件來進行滾動,因此禁止了瀏覽器的默認行爲。
我用的是IScroll5.2.0,在百度大法找到了參數設置的方式:初始化時參數preventDefault: false,聽說這種方式會對iscroll設計初衷流暢度有所影響,經個人實踐。。。這種方式解決了瀏覽器默認事件無效的問題,可是,在該DOM元素上添加click事件仍然是無效的。
最後,在handleEvent方法的click分支處理中添加代碼:&& !utils.preventDefaultException(e.target, this.options.preventDefaultException),完美解決問題。
爲了以防萬一,在初始化時入參還添加了taps:true,最後發現,刪掉preventDefault: false也不會影響功能了。
IScroll初始化:
var _myScroll = new IScroll('#wrapper', { probeType: 3, mouseWheel: true, click: zeptoCommonFun.iScrollClick(), taps:true });
IScroll源碼修改:
case 'click': // if ( this.enabled && !e._constructed ) { // var target = e.target; // while (target.nodeType != 1) target = target.parentNode; // if (target.tagName != 'INPUT') // e.preventDefault(); // e.stopPropagation(); // } if (this.enabled && !e._constructed && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) { e.preventDefault(); e.stopPropagation(); } break;
如下是問題:
一、在解決touchstart、touchmove、touchend引起的問題的時候順帶解決了一個不知名bug,這個頁面上有個輸入框,每當輸入框開始輸入數據後頁面就會白屏,只留下孤獨的光標在那裏閃爍,輸入點擊完成後頁面又顯示出來了,這個只是IOS上的問題,奇怪的是,尚未開始找緣由,解決了頁面卡死事件後這個問題也莫名其妙的不見了,簡直靈異。。。
二、解決最後一個問題的時候由於傻逼加上了fastclick,又引起了個人頭腦風暴,fastclick可以解決移動端的300ms延遲問題,那按理說我加上了以後點擊應該比以前反應快一點纔對,爲何反而須要屢次點擊才能跳轉連接呢????
作這個總結的時候已是項目發版本的晚上8點,加班狗已哭暈在廁所,這一次的項目我學到很多好東西,雖然連加了兩週的班,畢竟無慾無求,也就無所謂了。
注:文章初發伊始便發現有很多朋友閱讀並轉載了該文,但使人氣憤的是原封不動的轉載居然不註明出處,我將本身的經驗以及踩過的坑作了總結而且發佈出來是爲了利人,利己,但願同是碼農的你能少走些彎路,但,也但願你們在摘取個人勞動成果的同時,請尊重個人勞動成果,謝謝!