前言
最近碰到幾個惡心問題,也發現一點優化技巧,以及對Hybrid知識的一些整理,這里便一並拿出來做分享了,關於Hybrid的調試,會是我今后一個重點
我的博客首先是學習筆記,方便自己做知識沉淀,以后好查閱,其次才是分享,所以其中有誤請提出,覺得亂是很有可能的~~~~~~
我們在工作中一般會有這么一個流程:發現問題->定位問題->解決問題
其中最難就是定位問題,有時候我們會花上幾天時間定位問題,而解決問題卻只需要幾秒......
所以定位問題的能力非常重要,這也是經驗的體現,所謂高手其實就是坑踩得多而又善於總結罷了
我這里首先分享一個坑爹的問題,然后由此問題展開今天的學習
JSON.stringify出BUG啦!
沒錯,這個我最近碰到最為惡心的一個問題!!!
所有頁面,本來在手機上好好的,就算所有手機、奇葩機都測試通過了,最后Hybrid聯調時總會出兩個莫名其妙的BUG
PS:不知道Hybrid各位聽過么?沒有聽過的前端需要好好補補課了,最近2年這個可能是一大趨勢,在與Hybrid的戰斗中,Hybrid表現出了移動開發萬惡之源的應有素質,配合索尼小米三星組成了一個難以逾越的障礙牆(UC我們就不提了)
問題的現象是,一個服務器下發的數據對象被存到了localstorage中,拿出來后其中的小數變成null了
該問題暫時發現發生於
Hybrid
三星S3 Sony L39H中,應該還有不少其它低端機型有問題。
幾經定位發現現象如下:
var testObject1 = { OrderAmount: 0.11 }; JSON.stringify(testObject1) => OrderAmount: null
① 進頁面便觸發這段代碼不會出問題~~
② click事件中執行上面代碼在60%的概率中便中招了!
最初我當然不相信原生的JSON.stringify會出問題,便反復測試,反復定位,最后頁面的代碼刪到只有幾行的時候,我不得不承認是他出了問題~~~~~~Hybrid就是讓你料想不到
一旦定位問題后,這里的解決方案也便出來了:
在Hybrid中判斷useAgent,重寫掉JSON.stringify的邏輯即可,這里貼一段參考代碼:
var json2 = { type: function (obj) { if (obj == null) return String(obj); var h = { '[object Boolean]': 'boolean', '[object Number]': 'number', '[object String]': 'string', '[object Function]': 'function', '[object Array]': 'array', '[object Date]': 'date', '[object RegExp]': 'regexp', '[object Error]': 'error' }; var t = Object.prototype.toString.call(obj); if (t in h) return h[t]; if (t == '[object Object]') t = obj + ''; var arr = t.match(/^\[object (HTML\w+)\]$/); if (arr) return arr[1]; return 'object'; }, stringifyJSON: function (obj) { var str, t = window.JSON; var rstringifyJSON = /([\n\r\f\\\/\'\"])/g; var arr = [], i = 0, n, p; var stringHash = { '\n': '\\n', '\r': '\\r', '\f': '\\f' }; switch (json2.type(obj)) { case null: str = 'null'; break; case 'undefined': str = 'undefined'; break; case 'object': for (p in obj) { if (obj.hasOwnProperty(p)) { arr[i++] = json2.stringifyJSON(p) + ':' + json2.stringifyJSON(obj[p]); } } str = '{' + arr.join(',') + '}'; break; case 'array': for (i = 0, n = obj.length; i < n; i++) { arr[i] = json2.stringifyJSON(obj[i]); } str = '[' + arr.join(',') + ']'; break; case 'string': str = '\"' + obj.replace(rstringifyJSON, function (a) { return stringHash[a] || '\\' + a; }) + '\"'; break; case 'date': str = 'new Date(' + obj.getTime() + ')'; break; case 'number': case 'boolean': case 'function': case 'regexp': str = obj.toString(); break; default: str = 'null'; } return str; } }; JSON.stringify = json2.stringifyJSON;
當然,我這里其實挖掘的不夠徹底,我只是定位到了JSON.stringify有問題,卻不能再定位里面哪個環節有問題了......
更加優雅的做法:
var stringifyFunc = JSON.stringify JSON.stringify = function () { if (arguments.length == 1) { return stringifyFunc.call(this, arguments[0], function (k, v) { if (!isNaN(v)) return v + ''; else return v; }) } else { stringifyFunc.apply(this, arguments); } }
localstorage讀取失效
上面說到了localstorage,這里正好將它拿出來說下,首先有幾個必須要牢記的規則
① localstorage最大字符為500多萬(5M)
各個手機有所差異,但是不會太大,所以使用localstorage一定要記得清理,不清理可能導致
讀取localstorage效率下降,localstorage滿了會引發業務邏輯錯誤
② localstorage讀取文件的
所以其性能沒有內存讀取快,firefox更是會一次性將數據導入內存,想想就覺得嚇人啊
③ localstorage不被爬蟲識別,所以與SEO相關的關鍵信息需要避免使用localstorage,否則后續會被坑死
上面說了幾個localstorage需要注意的地方,事實上localstorage對性能提升還是有一些作用的
存儲不太重要的數據,比如城市信息;存取1分鍾內有用的數據也是可以減少請求的
但是在android Hybrid中有一個神奇的后退按鈕,此按鈕一旦按下會回到上一個頁面,這個時候里面的localstorage可能會讀取失效!!!一個簡單不靠譜的解決方案是在webapp中加入:
window.onunload = function () { };//不要問我為什么,我也不知道!
最后在開啟隱私模式下時,safari的localstorage讀寫是不可用的,但是qq瀏覽器卻可以,至於原因我就不知道了......
消除鏈接失效時safari alert框
該問題的使用場景首先出現在這里:
導致alert框的出現的原因是我點擊了一個無效鏈接,這個時候Safari便會彈框提示
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <meta name="viewport" content="width=320.1, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no,minimal-ui"> </head> <body> <a href="http://www.baidu.com">百度一下</a> <a href="taobao://wireless">測試無效URL</a> </body> </html>

前段時間,小釵的一個同事找到了解決方案,大致做法如下:
1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <title></title> 4 <meta name="viewport" content="width=320.1, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no,minimal-ui"> 5 <script id="others_zepto_10rc1" type="text/javascript" class="library" src="/js/sandbox/other/zepto.min.js"></script> 6 </head> 7 <body> 8 <a href="http://www.baidu.com">百度一下</a> <a href="taobao://wireless">測試無效URL</a> 9 <script type="text/javascript"> 10 $('a').click(function (e) { 11 var el = $(e.target); 12 var url = el.attr('href'); 13 if (url.indexOf('taobao') != -1) { 14 var ifm = document.createElement('iframe'); 15 ifm.onload = function () { 16 ifm.contentWindow.document.write('<script>location.href="' + url + '"</' + '' + 'script>'); 17 } 18 ifm.src = 'about:blank'; 19 document.body.appendChild(ifm); 20 } else { 21 window.location = url; 22 } 23 e.preventDefault(); 24 }); 25 </script> 26 </body> 27 </html>
核心代碼在此:
1 $('a').click(function (e) { 2 var el = $(e.target); 3 var url = el.attr('href'); 4 if (url.indexOf('taobao') != -1) { 5 var ifm = document.createElement('iframe'); 6 ifm.onload = function () { 7 ifm.contentWindow.document.write('<script>location.href="' + url + '"</' + '' + 'script>'); 8 } 9 ifm.src = 'about:blank'; 10 document.body.appendChild(ifm); 11 } else { 12 window.location = url; 13 } 14 e.preventDefault();
其原理就是iframe中url解析錯誤的話,Safari不太理睬~~~~~~
延遲加載·性能與體驗
以延遲加載來說,最常見的便是圖片延遲加載,但是很多朋友卻不知道為什么要做延遲加載
瀏覽器能同時請求的並發數是有限的,對於手機來說一般是4-6之間,不同型號的手機或者瀏覽器會有所不同,差距不會太大
這個請求數限制存於瀏覽器,所以一處請求卡死,就算新開標簽也會受到影響(手機一般不考慮tab),下面有一個場景:
一個頁面打開,里面有N多圖片,並且有幾個js待加載,這個時候若是圖片先加載的話,圖片會占用js的並發數,從而阻塞頁面的加載~~~~~~
舉個webapp的例子,我們進一個列表頁,加載了15個圖片,用戶點擊列表項booking頁模塊js開始加載(requireJS規則),這個時候業務js需要等待前面圖片加載結束后才能加載,至少需要空閑並發數
所以,圖片是有可能堵塞JS的,這個也是我們做圖片延遲加載的主要原因
首屏載入速度
延遲加載是提升首頁載入速度的一大手段,對於webapp來說,操作會有所不同
webapp中一個個業務view都是一個獨立的js文件,我們能控制第二個view在首頁是否加載
或者說,頁面中用到的組件,我們皆可以按需加載,但這里就有一個情況需要取舍
首屏快,操作慢VS首屏慢操作快
說得多不如親身操作:
第一個便是首屏快的代碼,其它組件全部采用按需加載的手段,但是事實上這類做法會導致后續操作十分卡!!因為每一個操作可能引發一次請求!
第二個便是首屏將UI與View業務代碼全部打包一起了,這樣首屏加載會比較慢,他的效果時后續操作的無縫性
當然,是否需要將js全部打包,這會是一場口水戰,直接有一個閥值,有一個區間,只要做到這個區間便好
統計代碼導致10px白屏
很多大型網站都會具有統計代碼,而此類統計代碼一般是以img做請求發出,但是他可以導致10px白屏你知道嗎?


會出現10px左右的白屏區域,這個問題導致的原因是:
獨立的inline元素出現時,會為他創建一個line boxes,這個就是傳說中的文字框
一行文字有一個line boxes,line boxes的高度由line-height控制而不是行內元素的width height控制
所以,img的高度與line boxes沒有關系
下面那一行白屏空間其實就是一個匿名line boxes,這個時候給body設置line-height他便會消失,或者讓img脫離文檔流即可
結語
依舊這句話,問題的定位才是難點,若能定位一個問題,其解決方案往往是分分鍾的事情......
這里記錄這些奇怪的知識點,以便今后查閱,也希望對各位有所幫助!
