前言

最近碰到几个恶心问题,也发现一点优化技巧,以及对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>

前段时间,小钗的一个同事找到了解决方案,大致做法如下:
 <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">
<script id="others_zepto_10rc1" type="text/javascript" class="library" src="/js/sandbox/other/zepto.min.js"></script>
</head>
<body>
<a href="http://www.baidu.com">百度一下</a> <a href="taobao://wireless">测试无效URL</a>
<script type="text/javascript">
$('a').click(function (e) {
var el = $(e.target);
var url = el.attr('href');
if (url.indexOf('taobao') != -1) {
var ifm = document.createElement('iframe');
ifm.onload = function () {
ifm.contentWindow.document.write('<script>location.href="' + url + '"</' + '' + 'script>');
}
ifm.src = 'about:blank';
document.body.appendChild(ifm);
} else {
window.location = url;
}
e.preventDefault();
});
</script>
</body>
</html>

核心代码在此:

     $('a').click(function (e) {
var el = $(e.target);
var url = el.attr('href');
if (url.indexOf('taobao') != -1) {
var ifm = document.createElement('iframe');
ifm.onload = function () {
ifm.contentWindow.document.write('<script>location.href="' + url + '"</' + '' + 'script>');
}
ifm.src = 'about:blank';
document.body.appendChild(ifm);
} else {
window.location = url;
}
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脱离文档流即可

结语

依旧这句话,问题的定位才是难点,若能定位一个问题,其解决方案往往是分分钟的事情......
这里记录这些奇怪的知识点,以便今后查阅,也希望对各位有所帮助!

【小贴士】【stringify神BUG】【localstorage失效】【消灭Safari alert框】【是否延迟加载】【页面10px白屏】的更多相关文章

  1. Angular2 小贴士 Name

    Angular2 正式版已经发布了一个月了,我也是通过各种方式在进行验证是否可以满足我们的需求,今天我就发现了一个问题.现在我们来一起说明一下,这个可能不算是bug,而应该需要我们记住就可以了. 我们 ...

  2. SVN小贴士

    我辛辛苦苦写的到哪里了? SVN小贴士SVN服务器上的代码项目组公用,你的每一个提交都会体现给项目组每个人,所以提交要慎重,要注意避免代码冲突,使用SVN小贴士: 1.提前宣布开发计划,保持项目组成员 ...

  3. 初识bd时的一些技能小贴士

    既然小豆腐如此给力,而且充分的利用主动学习的优势,已经有了迅速脑补,压倒式的优势,不过这只是表面而已,一切才刚刚开始,究竟鹿死谁手,还有待验证. 以上可以看到,小豆腐为什么拼命的要teach我们了么, ...

  4. 初识bigdata时的一些技能小贴士

    既然小豆腐如此给力,而且充分的利用主动学习的优势,已经有了迅速脑补,压倒式的优势,不过这只是表面而已,一切才刚刚开始,究竟鹿死谁手,还有待验证. 以上可以看到,小豆腐为什么拼命的要teach我们了么, ...

  5. 【小贴士】虚拟键盘与fixed带给移动端的痛!

    前言 今天来公司的主要目的就是研究虚拟键盘与fixed的问题,期间因为同事问起闭包与事件委托(阻止冒泡)相关问题,便穿插了一篇别的: [小贴士]工作中的”闭包“与事件委托的”阻止冒泡“,有兴趣的朋友可 ...

  6. android性能小贴士 翻译

    转自http://developer.android.com/training/articles/perf-tips.html 性能小贴士: 这篇文档主要一些微优化可以提升应用程序性能,但是这些改变不 ...

  7. 小贴士——提高PHP程序在NGINX代理服务器的性能

    NGINX本身就是面向最大性能的代理服务器,因此在使用NGINX,并没有性能调整的配置工作.但是却有很多选项可用于定制NGINX的行为,利用底层硬件和操作系统. 下面将介绍用于提供PHP在NGINX的 ...

  8. jprofiler8使用小贴士

    说明:本文的小贴士是针对jprofiler8的,其他版本上可能有不适用的地方 贴士一:使用jpenable监控,无需增加jvm参数和重启 贴士一:使用jpenable监控,无需增加jvm参数和重启 j ...

  9. 小程序背景图片bug

    在pc端调试的时候已经可以看到出现背景图片了,但是在真机调试的时候却发现没有背景图片,那么原因是什么呢?真机调试和vconsole也看不出什么鸟,其实这是小程序的一个bug.另一种说法是:backgr ...

随机推荐

  1. Knockout中文开发指南(完整版API中文文档) 目录索引

    a, .tree li > span { padding: 4pt; border-radius: 4px; } .tree li a { color:#46cfb0; text-decorat ...

  2. EntityFramework 7 更名为EntityFramework Core(预发布状态)

    前言 最近很少去学习和探索新的东西,尤其是之前一直比较关注的EF领域,本身不太懒,但是苦于环境比较影响自身的心情,所以迟迟没有下笔,但是不去学习感觉在精神层面缺少点什么,同时也有园友说EF又更新了,要 ...

  3. MyEclipse的项目中把 java EE 5 Libraries 删掉后怎么重新导入

    myeclipse中鼠标右击项目->properties->java Build Path=>Libraries=>Add Library...=>选择MyEclipse ...

  4. jQuery之on

    在jQuery1.9版本中,已经去掉了live和delegate方法,从而将on方法的地位进一步提升. jQuery如此推崇on方法,必有其牛逼的地方.那么我们就有必要了解这个on,并在代码中利用它, ...

  5. ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

    为了加强安全性,MySQL5.7为root用户随机生成了一个密码,在error log中,关于error log的位置,如果安装的是RPM包,则默认是/var/log/mysqld.log. 一般可通 ...

  6. Hadoop入门学习笔记---part2

    在<Hadoop入门学习笔记---part1>中感觉自己虽然总结的比较详细,但是始终感觉有点凌乱.不够系统化,不够简洁.经过自己的推敲和总结,现在在此处概括性的总结一下,认为在准备搭建ha ...

  7. 原创:微信小程序入口猜想?

    昨天看到一篇文章:是有一个人逆向了微信源码,从中发现了很多关于小程序的未公开内容,然后发布了出来,不过很快作者就删掉了文章,而我也没保留,只是隐约留下来一点点印象,就是作者推测了很多个入口:作者删掉的 ...

  8. GeoServer中利用SLD配图之矢量图层配图

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1 背景 我们在ArcMap中可以直接通过symbol功能对图层进行定 ...

  9. Java操作Sqlite数据库-jdbc连接

    Java操作Sqlite数据库步骤: 1. 导入Sqlite jdbc 本文使用sqlite-jdbc-3.7.2.jar,下载地址 http://pan.baidu.com/s/1kVHAGdD 2 ...

  10. jQuery-1.9.1源码分析系列(十五) 动画处理——外篇

    a.动画兼容Tween.propHooks Tween.propHooks提供特殊情况下设置.获取css特征值的方法,结构如下 Tween.propHooks = { _default: { get: ...