【小貼士】【stringify神BUG】【localstorage失效】【消滅Safari alert框】【是否延遲加載】【頁面10px白屏】

前言

最近碰到幾個噁心問題,也發現一點優化技巧,以及對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; 
View Code

固然,我這裏其實挖掘的不夠完全,我只是定位到了JSON.stringify有問題,卻不能再定位裏面哪一個環節有問題了......javascript

更加優雅的作法:html

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瀏覽器卻能夠,至於緣由我就不知道了......java

消除連接失效時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>
View Code

核心代碼在此:android

 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不太理睬~~~~~~git

延遲加載·性能與體驗

以延遲加載來講,最多見的即是圖片延遲加載,可是不少朋友殊不知道爲何要作延遲加載
瀏覽器能同時請求的併發數是有限的,對於手機來講通常是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白屏你知道嗎?github

會出現10px左右的白屏區域,這個問題致使的緣由是:
獨立的inline元素出現時,會爲他建立一個line boxes,這個就是傳說中的文字框
一行文字有一個line boxes,line boxes的高度由line-height控制而不是行內元素的width height控制
因此,img的高度與line boxes沒有關係
下面那一行白屏空間其實就是一個匿名line boxes,這個時候給body設置line-height他便會消失,或者讓img脫離文檔流便可

結語

依舊這句話,問題的定位纔是難點,若能定位一個問題,其解決方案每每是分分鐘的事情......
這裏記錄這些奇怪的知識點,以便從此查閱,也但願對各位有所幫助!
相關文章
相關標籤/搜索