`
zha_zi
  • 浏览: 584154 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

h5,hybrid 开发中问题汇总

阅读更多

                H5开发问题总结 和jquery bug列表

 localstorage sessionstorage 存取对象的问题,

       local 和session 都无法直接存取对象,当你定义一个 json 以后 通过setItem 和getIem 后发现无法正常使用,应为local session 都是支持字符串的存取,所以这是需要两个步骤第一就是在存的时候吧json 转化成字符串,当取出的时候再把字符串解析成json 例如

var person={
      id:'xxx10010',
      name:'xxx'
}
//存对象
sessionStorage.set("person",JSON.stringify(person));

// 取对象
var p=JSON.parse(sessionStorage.get("person"));

 

服务器返回状态304

如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个304状态码.
简单的表达就是:客户端已经执行了GET,但文件未变化。
服务器对数据进行了缓存,所以直接返回给请求的是缓存数据
 

jQuery IE 下 show hide 特效消失

IE 浏览器下jquery 的一个bug 在 div 内部嵌套的div 如果有 top left 属性动画效果会失效例如

 

 

       jQuery  IE 下一个兼容性问题

$("dom")  当jQuery 引用一个dom后这个dom被删除掉,在ff或者chrome 下我们可以通过 append($(dom)) 原先引用的这个dom进行复原,但是ie下不支持这个炒作,如果dom删掉无法在使用这个jquery对象,例如$(dom).html() 都是不能操作的。

      jQuery IE 6 7 中事件对象属性timestamp为undefined

 我们某些时候是使用事件处理的一些高级特性,这里会有一个基本的事件冒泡的基本原理,就是事件源产生事件后会向上传递,但是冒泡时候不会使用同一个事件对象,代码说明

<div id='f'>
     <div id='p'>
       xxxxxxxxx
     </div> 
</div>

 以这个dom结构说明

$(document).on("click",function(e){
   // 当我点击内层div的时候会事件是会委托传递到document
   // 上下两个都可以捕获到事件e ,但是这两个事件e并不是同一个e对象
   // 所以在前置处理中传递数据参数都是不能通过e 设置的,但是这里有一个细节就是只要事件进行委托传递,所有捕获的时间对象中e.timeStamp 的值是一样的,这个值非常有用,有助于确定事件源,但是这个重要的属性在IE6,7,8 中是undefined 所以如果考虑兼容6,7,8就在在代码中对这个属性进行处理  
})
$("#p").on("click",function(){
 

})

 所以当在 ie 6,7,8中如何使用时间对象中的timestamp请考虑到兼容的问题

 

zepto 1.1.4 中data()bug 

1.1.4中data 希望还原数据的原本类型,例如“123123123123123564” 但是在还原的过程中的精度有损失,变成12312312312312500,导致大量的订单重复问题,1.1.6中则没有这种问题

 

        HTML 自定义属性兼容性问题

为HTML元素添加一自定义的属性非常方便,只须将其加到尖括号中即可,与内置属性地位相等。

如我们要为TextBox元素添加属性idvalue:

<input type="text" id="txtInput" name="txtInput" value="自定义文本">

只须在原来的控件后面加上:idvalue=”…”,成为:

<input type="text" id="txtInput" name="txtInput" value="自定义文本" idvalue="自定义值">

idvalue即可正式成为txtInput的属性,地位与其他属性相等

IE 下自定义属性可以直接通过document.getElementById("txtInput").idvalue

取值

 但idvalue在Firefox中却不能通过,主要是因为Firefox控制严格,所以这些自定义属性不能认识。经过调试,只能用document.getElementById("txtInput").attributes["idvalue"].nodeValue取得下也可以通过这个方式取得

 

 jQuery 中$("").attr("checked")版本问题

    jQuery 1.7 一下可以使用这种方式判断check是否选中,但是1.10 中只能使用is(":checked")的方式判断选中状态,坑爹

 

       关于html 的keyup事件 在H5 mobile 设备中不兼容的解决,完美解决监听输入框的输入状态

    在开发h5应用的时候有个搜索提示功能,但凡这种功能肯定是要借助keyup事件的,功能完成测试主要是模拟测试和Android设备的测试没有发现问题上线后,发现在ios设备上这个搜索功能有bug ,keyup不是完全失效,而是有问题反正是比较反常,无法达到预期效果,研究了一下发现很多ios设备有这些问题,有些是越狱后有问题,总之keyup不具有这种功能,想办法找替代品,

   这里要提到html5的新form 事件oninput 

oninput:HTML5将oninput事件标准化了,该事件用来检测用户的输入状态。当然,通过使用onkeydown或者onkeyup作为代替也是可以的,这些事件设计本意也并非如此,所以我们如果在H5 mobile开发中需要检测用户输入状态的都最好使用oninput 事件这样就完美解决了上述的各种问你,PC浏览器IE9以后才兼容这个事件,当然IE还有一个特有的检测用户输入状态的事件propertypechange 可以再低版本的ie代替oninput 事件

 

 

jQuery select 事件bug

<html>
<head>
<script type="text/javascript" src="res/jquery-1.7.1.js"></script>
<script type="text/javascript">
$(document).ready(function(){
  $("input").select(function(e){
    $("input").after("1111111111,"); 
	//e.preventDefault();
  });
   
  $("button").click(function(){
    $("input").trigger("select");
	
  });
});
</script>
</head>
<body>
<input type="text" name="FirstName" value="Hello World" />
<br />
<button>激活 input 域的 select 事件</button>
</body>
</html>

 这段代码很简单,就是绑定input 的select 事件,然后通过trigger 主动触发事件,按照道理是应该执行一次,但是在chrome 执行了两次或者三次,如果增加的e.preventDefault();就会恢复正常,证明chrome 在处理select 事件的时候是和ff ie 有所不同,带有了浏览器的缺省行为,所以导致了二次执行,1.7 和1.11 版本都有这个问题。

 

iphone 浏览器与android 浏览器对 日期格式解析的差别

例如 new Date( "2014-10-9").getTime() android 浏览器是识别的,ios 没法识别这个格式数据

 

iphone 浏览器与android 浏览器对click touch 等事件的差异

这个android 与ois 有非常多的差别,具体为 

1:手机浏览器有双击放大的操作,ios 和android 对click 都有延时的处理大概200ms,因为浏览会看用户是不是有双击浏览器的动作

2:如果android 设置了viewport 为禁止所以,那么浏览器就不会等待200ms 的延迟,ios没有这个属性

3:ois 在处理touch事件的时候会冒泡多父级的click 事件,非常恶心

 

手机无痕浏览时候对h5 的影响

ios 和安卓的无痕浏览会对sessionStorage 产生影响, 无法使用sessionStorage 的setItem getItem 等属性,所以当用户使用无痕浏览的时候会产生bug ,如果处理这个问题可以在程序中判断用户的浏览模式,或者使用if(sessionStorage )代码判断浏览器中是否可以使用

 

h5 mobile 下scroll 问题

一般开发菜单fix 功能功能在pc下都是通过scroll,但是我们在手机h5开发的时候发现scroll 只能出发一次

就是在滚动结束的时候触发,所以在手机浏览器下常规很多scroll 实现的功能都无法做到,为了解决这个问题需要借助touchmove 事件辅助,touchmove 可以在滑动时候监控前半段,滑动惯性部分是无法监控到的

 

ios safari 下数字识别为电话

ios safari 的h5页面中发现很多数字会自动识别为电话号码,点击可以自动拨打,这个是移动端safari 做了数字识别,自动判别电话号码,所以给开发带来了很多麻烦,可以通过<metaname="format-detection"content="telephone=no"> 

指令解决这个问题

 

IScroll.js 的使用问题

 在开发h5 的时候经常有一种场景就是滚动面板,

 例如上图的场景,简单的做法就是 直接左右div 中直接设置overflow:scroll 

这种做法会产生两个问题

1:有滚动条,尤其是有些安卓手机上无法直视,

2:滚动失效

3:点透

无论是视觉还是使用效果都不太好,对于商用比较高的公司业务明显没法胜任,

这种情况下还是选择一个控件解决问题,iscroll.js

官方例子很简单,本想考进去就能使用没想折腾一天才算解决,把问题记录一下

1:例子粘到自己的dom 结构下无法滚动,最后发现是dom 结构问题,iscroll 必须有着一定的dom 结构,如果结构出问题就会导致滚动失效,这个是个很常见问题

2:加载数据后没法滚动,iscroll.js 是个比较蠢的控件,它在初始化的时候会结算panel 的面积产生滚动,我们的数据一般都是动态加载的所以就会导致两个问题a: 原先数据少,现在增加了数据没法出现滚动效果,B:原先数据多现在数据少依然可以滚动,所以当我们每次增加或者减少数据都要调用指定的控件的refresh() 方法

调用这个方法切记在setTimeout()中,

3:浏览器和手机区别,浏览器下可以在隐藏的状态下使用refresh,app 中一定要等div完全出现后(针对动画效果)在使用refresh 才有效。

 

 

 H5 图片上传问题

问题1,我们在 移动端 做图片上传基本思想一般都是 用一个隐藏的<intpu type='file' style='display:none'> 然后通过一个漂亮的按钮绑定事件trigger("click") 这个dom ,但是jquery中的tirgger 在移动端中对file 不能请作用,ios 和android 的现象都不相同,网上有很多解决办法,我也找到一种就是多次trigger 就可以解决,.trigger("click").trigger("click");

问题2,ios 无法获取canvas 上的图片, 图片第一步就是通过dom file 节点把图片文件选中,然后把图片渲染到canvas 中,通过canvas 带有的转base64的方法把图片最终转化为字符串上传到服务器上,但是在ios下会出现频繁的canvas 获取base64 没有内容,有时候正常,android是正常的最后发现原因是在  uploadTemp.reader.addEventListener('load',function(){}); 问题是在文件读取load 事件触发的时候立刻让canvas 读取file的内容会出现无法读取的情况,通过加延时就可以解决

uploadTemp.reader.addEventListener('load', $.proxy(function () {
       // load 触发以后增加延时
       setTimeout(function(){

       },100);

});

 

IOS 下解决 fixed 问题

    h5开发常见的问题,通常出现的底部按钮或者顶部header的fixed ,我们在应用fixed的时候非常方便可以把按钮固定在屏幕底部,但是在ios下键盘弹出会顶起这个固定的按钮,按钮就悬在屏幕中间下不去了,除非收起软键盘,看了很多资料都没法解决这个问题,有一天想到一个非常简单的解决方案,主要思路分以下几步

1:监听键盘弹出方法很简单

$("input textarea").on("focus",function(){
     // 当软键盘弹起的时候把fixed 属性干掉,这样就不会顶起按钮出现一个错误样式了
     $("footer").css("position","inherit");
});

 

 

2:监听键盘收起事情 

   

$("input textarea").on("blur",function(){
    // 当软键盘收起的时候恢复fixed属性
    $("footer").css("position","fixed");
});

 

 部分android 设备touchmove 只能出发一次的问题

在Android下直接使用touchmove事件会在很多浏览器中出现每次操作只触发一次touchmove的情况。这是因为Android中对触屏事件奇葩解析造成的,在其它系统上没有这个情况。我们可以在touchstart事件中加入preventDefalut来解决,但这会带来其它问题。 
<meta name="viewport" content="width=device-width,user-scalable=no" />
<input id="coords"></input>
<script>
document.addEventListener("touchmove",function(e){
  var p=e.touches[0];
  coords.value="("+p.clientX+","+p.clientY+")";
});
</script>
 这个代码在Android(4.0.3)下只有Firefox(24)可以正常工作,Chrome(29)、QQ(4.4)、UC(9.3),全都都只能触发一次touchmove。解决的方法是在touchstart时加上preventDefalut。 
document.addEventListener("touchstart",function(e){
  e.preventDefault();
});
 加上这个代码后所有的浏览器都可以正常处理touchmove了,但是会出现其它问题。例如这个例子中有个INPUT:TEXT,如果把touchstart事件的默认动作给阻止了我们就无法选中这个控件,无法编辑这个文本控件里面的文字(有少数浏览器可以)。这只是一个例子而已,阻止了touchstart的默认动作会导致很多操作都失效。CLICK事件不触发、超链接无法,等。所以,我们除了阻止touchstart的默认动作之外还要对内部的一些特殊元素做处理。让那些特殊的元素上的事件不冒泡出去,以防止默认动作被阻止。 
document.addEventListener("touchstart",function(e){
  /^(?:INPUT|TEXTAREA|A)$/.test(e.target.tagName)||e.preventDefault();
});
 只有触发对象不是这些特殊元素时才阻止默认事件,这样就能避免特殊元素无法实现默认行为。这里的INPUT、TEXTAREA、A

 

设备下INPUT TEXTAREA 不能点击光标切换输入位置

待续。。。。。。。。。。。。。。。。。。

 

 

 

解决swiper 控件兼顾内容上下滚动

  在使用swiper控件做切换内容由于swiper slides内容比较多,左右滑动切换swiper同时还要上下滚动查看内容,但是swiper控件会对屏幕上的触摸事件做处理,影响到浏览器原生的滚动事件,解决思路

就是在每个Swiper slides 上优先监听事件,如果左右滑动就不处理,如果上下滑动就阻止事件冒泡

 gesture: function($el){
                //返回角度  
                function GetSlideAngle(dx, dy) {  
                    return Math.atan2(dy, dx) * 180 / Math.PI;  
                }  
   
                //根据起点和终点返回方向 1:向上,2:向下,3:向左,4:向右,0:未滑动  
                function GetSlideDirection(startX, startY, endX, endY) {  
                    var dy = startY - endY;  
                    var dx = endX - startX;  
                    var result = 0;  
   
                    //如果滑动距离太短  
                    if(Math.abs(dx) < 2 && Math.abs(dy) < 2) {  
                        returnresult;  
                    }  
   
                    var angle = GetSlideAngle(dx, dy);  
                    if(angle >= -45 && angle < 45) {  
                        result = 4;  
                    }else if (angle >= 45 && angle < 135) {  
                        result = 1;  
                    }else if (angle >= -135 && angle < -45) {  
                        result = 2;  
                    }  
                    else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {  
                        result = 3;  
                    }  
   
                    return result;  
                }  
   
                //滑动处理  
                var startX, startY;  
                $el.on('touchstart', function (ev) {
                    startX = ev.touches[0].pageX;  
                    startY = ev.touches[0].pageY;    
                }, false);
                $el.on('touchmove', function (ev) {
                    var endX, endY;
                    endX = ev.changedTouches[0].pageX;
                    endY = ev.changedTouches[0].pageY;
                    var direction = GetSlideDirection(startX, startY, endX, endY);
                    switch (direction) {
                        case 0:
                            break;
                        case 1:
                            ev.stopPropagation();
                            break;
                        case 2:
                            ev.stopPropagation();
                            break;
                        case 3:
                            break;
                        case 4:
                            break;
                        default:
                    }
                },false);
                $el.on('touchend', function (ev) {
                   
                }, false);  
            },

 

   

设备下INPUT TEXTAREA 不能点击光标切换输入位置

   这个解决方案不具有通用参考性,我们的输入光标不能切换输入位置是由于使用fastclick 导致的,所以解决方案是通过class='nofastclick' 去做特殊处理多fastclick 

 

 

移动设备输入特殊字符的问题

  最近项目中在邮箱校验的时候屡次出现问题,客户输入符合格式的邮箱以后校验就是无法通过,我们输入和用户一样的内容发现是可以校验通过的,因为通过记录报错日志分析后,发现用户在移动设备输入时候,输入的特殊符号,这个符号用肉眼是没法看出的特殊符号就是 name: SIX-PER-EM SPACE

1/6空格,在网上查询资料后发现产生的原因是用户在“中文输入法中输入英文” 这种情况下就有可能产生这个特殊字符,str.replace(/\u2006/g, '') 除去即可。

 

 

ios 设备下用户触发了scroll 导致fixed 出问题

   项目中发现了一个非常诡异的问题

我们在原先页面的底部有一个功能导航栏目,是使用fixed 属性如下图




 

还有一个是正常情况下隐藏的功能这个功能也是设置fixed 属性,如下图

 
 只要在ios 设备下用户把滚动条滚到底部,原先底部功能导航就不能使用了现象是不能被点中,

fixed 属性在ios下实在太可怕,问题没完没了哭

 

 

一、tap与click的区别

两者都会在点击时触发,但是在手机WEB端,click会有 200~300 ms。延迟来自判断双击和长按,因为只有默认等待时间结束以确定没有后续动作发生时,才会触发click事件。所以触摸事件反应更快,体验更好。
singleTap和doubleTap 分别代表单次点击和双次点击。
tap封装了touchstart、touchmove、touchend三个事件的处理(touchstart之后如果有产生touchmove则取消此次tap事件的产生) click则只是单纯的绑定了浏览器的click事件。

二、tap事件点透问题

点击会触发非当前层的点击事件,这就是点透。例如:点击a但是同时触发了b元素的click事件,因为tap事件是通过document绑定了touchstart和touchend事件实现,$('.a')上,当touchend事件冒泡到document上以后执行$(this).hide();此时$('.b'),就处在了页面的最前面,现在touchend冒泡到了document上,并且$('.b')在页面的最前面,然后就触发了click事件。

三、tap事件点透解决

1.github上有一个叫做fastclick的库,它能规避移动设备上click事件的延迟响应https://github.com/ftlabs/fastclick将它用script标签引入页面(该库支持AMD,可按照AMD规范,用require.js的模块加载器引入),并且在dom ready时初始化在body上,如:
$(function(){
new FastClick(document.body);
})

然后给需要“无延迟点击”的元素绑定click事件(注意不再是绑定zepto的tap事件)即可。
也可以不在body上初始化它,而在某个dom上初始化,这样,只有设个dom和它的子元素才能享受"无延迟"的点击。
因为fastclick源码不依赖其他库所以你可以在原生的js前直接加上
window.addEventListener( "load", function() {
FastClick.attach( document.body );
}, false );

或者有zepto或者jqm的js里面加上
$(function() {
FastClick.attach(document.body);
});

当然require的话就这样:
var FastClick = require("fastclick");
FastClick.attach(document.body, options);

实践开发中,当元素绑定fastclick后,click响应速度比tap还要快一点。
2.对于B元素本身存在默认click事件的情况,应用touchend代替tap事件并阻止掉A元素touchend的默认行为preventDefault(),从而阻止click事件的产生。
$("#aa").on("touchend", function (event) {
//很多处理比如隐藏什么的
event.preventDefault();
});

对于B元素本身没有默认click事件的情况(无a标签等),应统一使用touch事件,统一代码风格,并且由于click事件在移动端的延迟要大很多,不利于用户体验,所以关于触摸事件应尽量使用touch相关事件。

延迟一定的时间(300ms+)来处理事件
$("#aa").on("tap", function (event) {
setTimeout(function(){
//很多处理比如隐藏什么的
},320);
});

这种方法其实很好,可以和fadeInIn/fadeOut等动画结合使用,可以做出过度效果

理论上上面的方法可以完美的解决tap的点透问题,如果真的倔强到不行,改用click。特别是对于遮盖浮层,由于遮盖浮层的点击即使有小延迟也是没有关系的,反而会有疑似更好的用户体验,所以这种情况,可以针对遮盖浮层自己采用click事件,这样就不会出现点透问题。

hbrid 和 H5开发关于定位问题

 h5 定位问题一般会有三种

1. 自定义网页,在js调用h5的定位接口 getCurrentPosition() 但是返回结果为{},我在第一次碰到这个 问题的时候也是百思不得其解,但是如果你查看console 会发现 getCurrentPosition() and watchPosition() no longer work on insecure origins 这段提示,所以问题很简单,html5 不允许在非安全协议中使用定位功能,估计怕别人恶意获取你的定位信息

 

2.为什么官方提供非http 的demo 可以使用,而且可以获取到定位,这里你要了解到定位目前主流是采用两种形式,gps 和ip ,所以你看到定位信息是但是优势误差非常大这就是这个原因

 

3.webview 下使用file 协议肯定无法直接使用html5 geo 信息直接获取定位的。 如果使用定位,这种情况下一定要使用hybrid 接口获取定位信息

 

补充:上述情况并不是绝对,实际测试中发现个别手机(华为 core 6.0.2)可以在非安全协议下使用geo定位,但是我们还是认为官方希望是厂商的标准是在安全协议下使用定位功能

 

 

 使用富文本编辑器等,导致 post 数据被截断的解决方式

1.可以直接对数据encodeURIComponent 然后提交

2.使用{"":""}组合数据

$.ajax({
    type:"POST",
    url:"test",
    data:{"param":data},//使用此方式提交可避免字符串中特殊字符带来的数据截断的问题
    success:function(str){
       ......
    }
  });

   

 ios  wkview 打开多个页面,页面之间不能共享localstorage cookie  信息

  本质原因是由于ios 对wkview 进行了优化,当用户保存了cookie storage 等数据是没有立刻更新到存储中,而是暂时在内存中,所以当我们在快速操作的时候 就不能取到数据, 比如  a.html, b.html 分别在两个webview中而且是同域, b.html 保存了数据按道理回到a页面是立刻可以拿到的,android是正常,但是ios 不可以,解决办法是

The init of WKWebViews can receive a parameter WKWebViewConfiguration with a variable called processPool that represents all the web content (including localStorage, IndexedDB, cookies and so on) process.

 

So for the WKWebViews to share in real-time all the memory management, you need to declare a unique WKProcessPool for all of them.

 

let uniqueProcessPool = WKProcessPool()

let configA = WKWebViewConfiguration()
configA.processPool = uniqueProcessPool
let webViewA = init(frame: CGRect.zero, configuration: configA)

let configB = WKWebViewConfiguration()
configB.processPool = uniqueProcessPool
let webViewB = init(frame: CGRect.zero, configuration: configB)

 关于ios wkwebview中加载页面后不能滑动

   出现的原因 是由于div 当原始没有设置高度高度,后来被内容撑开导致的。

 

 

 

  h5 开发中因为设置了 position = fixed 导致滚动到页面顶部和底部的时候会出现抖动的情况

  

  vue 开发中scroll 事件失效的处理方式

 

  • 大小: 16.8 KB
  • 大小: 5.5 KB
  • 大小: 4.5 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics