每个客户使用的设备都各不相同,所以会出现各种品牌手机样式或者js不兼容的情况,这里我们在做项目中也遇到并记录了各种兼容问题的一些产生与解决方案,避免以后再次出现兼容性问题影响客户体验,同时在代码编写上就提前规避到兼容问题,提高开发效率。

一、iOS中多个position:fixed中z-index失效导致的坑

项目中难免会遇到一些弹框提示,在ios苹果手机,多个position:fixed导致层级关系失效,弹窗无法显示。怎么调试都无法实现(如图),部分苹果手机不会出现此问题。

前端解决ios内嵌兼容 ios兼容性_javascript

对于这个兼容性问题这边进行实践后总结出以下解决方案:

方法一:页面上加上 iOS的弹性滑动属性-webkit-overflow-scrolling: touch会导致苹果上z-index属性失效,安卓正常 ,将弹性滑动属性的css全局样式-webkit-overflow-scrolling: touch去掉后z-index属性正常。
方法二:写js弹窗出现时,隐藏上层层级的div【底部菜单】;弹窗取消时,显示上层层级的div【底部菜单】
方法三:在出问题的弹框上面添加一下css样式亦可解决问题
transform: 'translateZ(1px)'

二、IOS中搜索输入框获取焦点问题

苹果手机在获取搜索输入框焦点的时候,输入框显示没有背景颜色,没有边框,输入框变的很诡异,用户体验不佳,具体问题如图。

前端解决ios内嵌兼容 ios兼容性_ios_02

这个兼容问题原因主要是因为ios手机在获取焦点的时候应用了浏览器的默认样式将input的背景色以及边框给变成了白色以至于出现这个问题。解决办法为:

#在搜索框写入如下样式,也可设置为全局样式
input[type='search'] {
   -webkit-appearance: none;
}

三、移动端页面物理返回上个页面后数据没有更新

部分安卓与苹果手机在移动端网页操作物理返回键返回到上个页面的时候页面上的数据没有更新为最新,导致数据显示错误问题(如图):

前端解决ios内嵌兼容 ios兼容性_ios_03

在操作物理返回键后,当前页面没有去拉取数据,并没有像后端发送接口,使用的浏览器的缓存逻辑,这样完全不是我们想要的效果。这里有如此解决方案,监听页面‘pageshow’方法,在页面显示的时候进行判断是否是从上个页面返回回来,如果判断成功则进行接口数据拉取,同步最新数据到页面。具体代码如下:

window.addEventListener('pageshow', (e) => {
      // 使用 PageTransitionEvent 对象的 persisted 属性来判断。如果页面从浏览器的缓存中读取该属性返回 ture,否则返回 false
      // performance.navigation.type [0:点击或url进入; 1:为点击刷新或location.reload; 2:历史记录或前进后退; 255:其他方式]
      if (
        isPageHide ||
        (isDefaultRefresh &&
          (e.persisted || (window.performance && window.performance.navigation.type === 2)))
      ) {
        //在此进行数据的重新拉取以及同步到页面显示
      }
});

四、低版本ios使用html2canvas截图空白以及ios页面滑动后截图空白问题

因业务项目需要,在手机端网页上生成海报图并附带用户信息,这时就需要使用html2canvas进行页面截图生成图片供用户分享。

1、低版本空白

在高版本的ios机器上图片生成功能都一切正常,但是到ios10以下图片生成不了,仔细查找发现是其中代码的写法低版本并不兼容,所以需要在生成图片的时候对用户手机版本进行判断来是使用对应的方法。具体实现代码如下:

html2canvas(this.$refs.imageWrapper, {
		backgroundColor: null // 解决生成的图片有白边
	}).then(canvas => {
		let dataURL = canvas.toDataURL("image/png");
     	let storeAs = "writing" + "/" + this.timeName() + "/" + this.getUuid() + "." + "png";
     	
        if(this.ios > 9){
          this.imgFile = this.getBase64Img(dataURL);
        }else{ //低版本执行方法
          let bold = this.getBase64Img(dataURL);
          let file = this.blobToFile(bold, "fileName");
        }  
});

getBase64Img: function(file) {
      	let fileName = "writing.png"; //图片名称
      	var arr = file.split(","),
      		mime = arr[0].match(/:(.*?);/)[1],
      		bstr = atob(arr[1]),
      		n = bstr.length,
      		u8arr = new Uint8Array(n);
      	while (n--) {
      		u8arr[n] = bstr.charCodeAt(n);
      	}
    	if(this.ios > 9){
      	  return new File([u8arr], fileName, {
      	  	type: mime
      	  });
      	}else{ //低版本执行方法
      	  return new Blob([u8arr], {
      	  	type: mime
      	  });
       }
},
//Blob方式获取图片方法
blobToFile: function(Blob, fileName) {
  Blob.lastModifiedDate = new Date();
  Blob.name = fileName;
  return Blob;
},

//获取ios版本方法
isIos() {
	var str= navigator.userAgent.toLowerCase();
    var ver=str.match(/cpu iphone os (.*?) like mac os/);
    if(ver){
      let num = ver[1].replace(/_/g,".").split(".")[0]
      //console.log("你当前的Ios系统版本为:",num);
      this.ios = num
    }
}
2、页面滚动导致的空白

在绘制海报图片中,ios手机如果滚动页面后再进行绘制的话,绘制的图片有一部分会是空白的情况,这是因为图片的绘制是从body开始定位x、y的距离,页面滚动后body已经被向上滑动了,所以会导致图片绘制错误的问题(如图):

前端解决ios内嵌兼容 ios兼容性_前端解决ios内嵌兼容_04

具体解决办法是设置html2canvas的参数scrollY:0来固定body的滚动高度。

var myCanvas = document.getElementById('thecanvas');
  html2canvas(myCanvas, {
      allowTaint: true,
      useCORS: true,
      scrollY: 0,
  }).then((canvas) => {
      var imgDataUrl = canvas.toDataURL('image/png');
      setImgData(imgDataUrl);
  });

五、1px边框问题

在不同的手机上面,设置1px边框的时候,它展示的宽度也不一样,在个别手机上会显的特别粗,具体解决方法通过把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位来实现。具体代码:

.border{
    position: relative;
    border:none;
  }
 .border:after{
    content: '';
    position: absolute;
    bottom: 0;
    background: #000;
    width: 100%;
    height: 1px;
    transform: scaleY(0.5);
    transform-origin: 0 0;
 }

六、输入框点击键盘弹起挡住输入框问题

在手机浏览器或者微信公众号中录入数据的时候,当录入到页面底部数据时,点击输入框调起键盘的时候,弹起的键盘会悬浮在页面上,会将我们正在获取焦点的输入框给遮盖掉(如图),这样用户体验很不好。

前端解决ios内嵌兼容 ios兼容性_css3_05

解决方案:

var inputTextBox = document.getElementById('input-box');

setTimeOut(function(){

	inputTextBox.scrollIntoView(true);

},200)

七、IOS系统中日期时间转换问题

在IOS系统日期转换时,不能使用"-“做链接符,如果用”-“做链接符会出现NAN的情况,类似于这种操作: new Date(‘2020-12-23 00:00:00’)。在ios中需要用”/"作为日期的连接符已解决问题。

new Date('2020/12/23 00:00:00')

八、ios的body设置overflow:hidden仍然可以滚动

在部分的ios手机上弹框层的时候给body设置了overflow:hidden禁止body滚动,但是拖动body还是可以滚动,就非常神奇。最后找到解决办法在所有元素最外层再包一个大盒子.wrap然后设置下面的样式再次禁止滚动来实现。

.wrap{
      position:relative;
      overflow:hidden;
  }

九、移动端滚动穿透

在移动端网页中如果有弹出层并且弹出层的内容是可以滚动的情况下,会出现滚动穿透的情况,滚动弹出层的内容后面的body会跟着滚动。实现方法有两种:

方法一、弹出弹框时,使背景主页内容作为固定定位,这样页面的滑动对其就没有任何影响,关闭弹框使,移除这个固定定位的类名,回复正常
<script type="text/javascript">
  //解决遮罩层滚动穿透问题,分别在遮罩层弹出后和关闭前调用
  const ModalHelper = ( (bodyCls) =>{
    let scrollTop;
    return {
      afterOpen: function () {
        scrollTop = document.scrollingElement.scrollTop;
        document.body.classList.add(bodyCls);
        document.body.style.top = -scrollTop + 'px';
      },
      beforeClose: function () {
        document.body.classList.remove(bodyCls);
        // scrollTop lost after set position:fixed, restore it back.
        document.scrollingElement.scrollTop = scrollTop;
      }
    };
  })('dialog-open');
</script>

body.dialog-open {
  position: fixed;
  width: 100%;
}
方法二、tua-body-scroll-lock插件的正确使用

使用tua-body-scroll-lock时lock 要加在真正滑动的层上(overflow: scroll/auo;)。如果 unlock 是比较混乱了,可以直接使用 clearBodyLocks。

十、安卓部分版本input的placeholder偏上

安卓部分手机的input框里面的placeholder的提示语显示会跟input没有对齐会向上偏移了一部分。出现这个问题的解决方法是将input的line-height设为normal来解决这个问题。

input{
   line-height:normal;
}