移动端踩坑解决方法汇
前段时间在小密圈和大家分享我的感受,H5代替客户端进行移动端开发,是大趋势。未来较长一段时间,是混合应用的天下。然而H5写移动页面,那绝对是一步一个坑的节奏啊,做好各设备的兼容将是各前端er的重要使命。今天给大家送上一个解决一些坑的办法,是我最近开发中遇到的一些坑,作个记录,也给大家一些经验。
1.babel-polyfill老实加上。现在很多项目都用ES6在写了,ES6在移动端的兼容也天生较好。有些同学嫌弃polyfill文件太大(压缩后也将近100KB)就不引了,反正用到的方法也不多。
然而最近发现项目在魅族手机上报错,查看原因发现是没有Array.includes方法,而该项目也正是我说的没引babel-polyfill的情况。所以,为了保险起见,还是老实引入吧。当然也可以按需引入对应方法,这样的话成本又高了,你没法预见项目将来还会用哪个方法。
2.同事反馈,ios上某个页面,输入框里一输东西就闪退。我当时诧异,一个输入框怎么有本事把应用给搞崩。
经排查,原因令人大跌眼镜。场景是这样的:在点击input标签的时候,根据一些逻辑来判断是否应该给加readonly属性。在手机上,点击动作可能有延迟,在逻辑判断生效之前,键盘已经弹出来了,然后input才被设为readonly。此时如果用键盘输入东西,系统就直接闪退了!没错,是闪退了。因为你在往一个readonly的输入框里写东西。
当然这里也是逻辑的问题,一个input框,应该在其被点击之前,就把readonly属性确定好的。
3.forEach去循环NodeList不靠谱。querySelectorAll返回的是NodeList类型,而forEach是Array上面的方法。大部分浏览器有做兼容,用forEach去循环NodeList这样的类数组,也是能干活的。
然而也不是百分百,发现在vivo手机上就不行,直接报错。所以还得老实用for循环去取。有人说可以先把类数组转成数组呀,但我觉得为了循环而转,反而产生额外的开销。
4.fixed定位在iOS的不完全支持。大家知道iOS原先是不支持fixed定位的,在后来的系统版本中做了支持。
但是在最近的测试中发现,当fixed元素的内容很多,既DOM节点嵌套非常多的时候,fixed元素在一顿乱滑的操作下,竟然被滑走了!可见在最新的iOS10下,fixed的支持也是不完美的啊。
所以我一般用absolute定位+局部div滚动来实现固定定位。
5.click能点透,也能上冒。click事件点透的现象,做移动端开发的同学应该知道,前几年网上也很多分析文章。其实核心问题就是,在事件派发的过程中,当前点击元素突然消失,导致事件被“嫁接”在了别的元素上。
最近遇到的一个坑是,当一个元素绑定了touchstart事件,如果点击的过程中,页面突然弹出一个层,那么click事件也会发生在这个层上面,感觉像上冒了一样。
6.这个问题,是为了解决5而引出的。我尝试给touchstart事件加了preventDefault,结果整个页面滚不动了。原因是把默认的scroll动作给禁止了。看来是不能随意给touchstart事件加preventDefault的。
7.vue在iOS上的性能缺陷?项目整体用了vue,发现某些特定的操作,在iOS上有明显的延迟。我不敢确诊是vue的问题,只是就表象来做总结。
存储在store中的数据,在组件中进行watch,发现更新会缓慢。
频繁修改数据的绑定,比如audio的progress事件,页面进行style绑定的时候,当系统多次键盘弹出后,实时更新会失效,我不得不手工操作DOM。
给事件用了修饰符,比如.stop/.prevent,监听函数的执行有明显延迟。
8.按home键切入后台后的情况。iOS和安卓都要注意,可能需要处理的东西有:延迟延时是否还是执行、音频是否能继续播放、Promise链是否在继续执行。
如页面有以上操作,需要注意一下,在按home键进入后台,再返回的时候页面是否还正常。
相应的处理办法,有Page Visibility API,但是要考虑兼容。最好是让壳来提供API,这样比较稳妥。
9.vue组件的销毁。vue组件有$destroy方法,一般不用,但是如果要用到,注意它只是销毁Vue实例。在store中存储的相关状态,需要手动去重置。页面上的HTML节点,需要手工去删除。
10.vuex自动注册问题。这个跟移动端关系不大,也是遇到的,一并说吧。
vuex会自动检测是否有全局的Vue变量,有的话会自动注册。如果你在代码中再次use,则会报错。我尝试想办法检测vue是否已注册了vuex,但是没找到方法。最后只得这样来判断:if(window.Vue && window.Vuex)。这样表明vuex肯定已被注册过了。