【小贴士】【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脱离文档流便可

结语

依旧这句话,问题的定位才是难点,若能定位一个问题,其解决方案每每是分分钟的事情......
这里记录这些奇怪的知识点,以便从此查阅,也但愿对各位有所帮助!
相关文章
相关标签/搜索