移动端兼容性问题(建议码住,持续更新哦~)

最近开发移动端较多,整理了一下最近遇到的一些兼容问题

1.1px在移动端的解决方案

最开始当然从移动端的兼容性适配开始了,关于的详细解释,在我上一篇博客中已经大概讲了一下,1px在移动端的解决方案,问题产生的原因就是在于不同dpr的设备上,1px的css样式像素会产生不同的效果。

  • 对于老项目,最好的解决方案可以使用css3中的transform结合伪类::after/::before来进行缩放解决;
  • 对于新项目,可以使用viewport+rem,可以全局性的设置缩放比例,并设定全局根元素的rem,
    头部的原始状态设为:
<meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">

js动态修改的部分:

var viewport = document.querySelector("meta[name=viewport]")
if (window.devicePixelRatio == 1) {
    viewport.setAttribute('content', 'width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no')
} 
if (window.devicePixelRatio == 2) {
    viewport.setAttribute('content', 'width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no')
} 
if (window.devicePixelRatio == 3) {
    viewport.setAttribute('content', 'width=device-width, initial-scale=0.333333333, maximum-scale=0.333333333, minimum-scale=0.333333333, user-scalable=no')
} 
var docEl = document.documentElement;
var fontsize = 10 * (docEl.clientWidth / 320) + 'px';
docEl.style.fontSize = fontsize;

详情可以移步这里

2.当字号小于12px时,安卓中文字无法垂直居中

3.移动端实现,键盘点击,用户唤起搜索功能(即enter键?)

<form action="javascript:void(0)">
<input
      name="search"
      v-model="searchValue"
      placeholder="请输入公司简称或产品名称"
      ref="searchInput"
      @keyup.13="searchAllData()" />
</form>

Tips:

  • 不管是安卓还是苹果手机,搜索按键的keycode都是13,这里是vue项目,可以使用按键修饰符。
  • 用type="search"来统一安卓和苹果机的搜索按键。
  • 必须在input标签外面套上form表单,并设置 action=“javascript:void 0”,action属性很关键,才能实现搜索功能,不能省略。
  • 若想添加自动聚焦功能,可以先获取当前input这个dom元素,再添加focus()方法;
this.$nextTick(() => {
this.$refs.searchInput.focus()
 })

4.当使用position定位时,css3中transform的等级高于position定位

里面涉及到对于层叠上下文的知识理解,具体可以参考鑫旭大大的博客

5.safari浏览器(包含ios的微信浏览器,一个内核)在ios中返回上一级不会刷新页面,但是安卓会重新刷新页面

(1)针对这种问题,当时的产品的方案是要保留缓存,返回上一级页面时,会记住用户的筛选记录,对于安卓端的刷新页面的现象,当时的解决方案是将用户的筛选条件记录在sessionStorage里面,当返回上一级页面时,从缓存中读取记录,并重新请求。在监听用户跳转页面的行为中,存在两种情况:

  • 一种是vue内置的vue-router路由跳转
  • 一种是js里面使用window.lcaotion.href跳转

针对这两种跳转方式,在使用监听事件onbeforeunload时,引出了兼容性问题8
(2)针对safari不想留住缓存的情况,渴望刷新,新增解决方案:
监听页面的pageshow事件

 if(isIOS()){
	  window.addEventListener('pageshow', function (event) {
	        if (event.persisted || window.performance &&
	                window.performance.navigation.type == 2)
	        {
	            location.reload();
	        }
	    },false);
    }

6.微信内置浏览器深层嵌套一层webview,ios导致偶尔会出现滑动到底部,下滑困难,内部无法滑动,需要倒退1px才可以

这个问题同理滑动到顶部,会出现上滑困难,内部无法滑动,需要倒退1px才可以。
解决方案在于这个1px上面,废话不多说,上代码!

/**
 * 判断是否为ios
 */
export function isIOS () {
  return !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
}
/**
 * 微信浏览器判断
 */
export function isWXBrowser () {
  var ua = window.navigator.userAgent.toLowerCase()
  if (ua.match(/MicroMessenger/i) == 'micromessenger') return true
  return false
}

// 重点在这里哦,微信环境ios下触底或者下拉回弹1px
/**
 *
 * 微信浏览器 IOS 容器内滚动到底或到顶,再次快速滑动会出现无法滑动的bug
 * @export
 * @param {obj} e 容器的节点
 */
export function fixIosScroll (e) {
  if (!isIOS && !isWXBrowser) return
  const scrollHeight = e.scrollHeight
  const scrollTop = e.scrollTop
  const clientHeight = e.clientHeight
  // 滚动条在顶部,回退1px
  if (scrollTop === 0) {
    e.scrollTop = 1
    return
  }
  // 滚动条触底,向上1px
  if (scrollHeight - scrollTop === clientHeight) {
    e.scrollTop = scrollTop - 1
  }
}

7.微信分享功能,偶现初始化失败,默认会直接分享当前window.location页面,使用vue中的路由router跳转无法获取当前页面。

针对微信jssdk的初始化失败的情况,vue项目中无法默认分享当前页面,解决方案是,跳转当前需要分享的页面时不使用vue-router路由跳转,而是window.location,href跳转,改变window.location的值,实现初始化失败时默认分享当前页面

8.微信浏览器移动端不支持window.open打开新的窗口,不支持onbeforeunload页面卸载事件

在监听页面地址变化的时候,我开始使用的是onbeforeunload事件,用来针对vue-router跳转和window.location.href跳转两种情况都很有效果。是在使用谷歌浏览器内置的移动端模拟器上面是ok,ok,ok……的,But……(黑脸表情。。。)当我在手机上面真机调试的时候,竟然不起作用,没有效果!!!!

所以,我不得不放弃了这个onbeforeunload,??
最后,分成了两种来判断,vue-router跳转使用路由内置的钩子函数beforeRouteLeave来添加(这个监听不到window.location.href跳转哦);
window.location.href则在添加跳转的事件里面捕获;


另外,提一嘴,H5新增的历史记录监听事件,通用性感觉不高:

  • window.onpopstate:当调用history.go()、history.back()、history.forward()浏览器的几个前进后退时触发;pushState()\replaceState()方法不触发
  • window.onhashchange:当前 URL 的锚部分(以 ‘#’ 号为开始) hash值发生改变时触发

另外补充一点:

使用onpagehide可以检测浏览器页面的关闭事件触发,以及监听页面window.location.href的跳转事件,但是对于vue的单页面router跳转是捕捉不到的,可以使用destoryed或者beforeRouteLeave路由的钩子函数来监听

或者onunload也是可以尝试使用的方法之一

9.当使用input输入框输入时,ios出现软键盘后,页面会被顶上去,收起键盘,页面下方留白

10.微信H5中ios有页面回弹的效果,安卓没有

11.在移动端浏览器中(至少在微信环境中),打开http://XXXX.pdf预览pdf文件,ios可以直接预览,安卓必须先跳转浏览器下载后才能看

解决办法:引入pdfh5.js插件,跳转另外一个html网站的链接页面,在这个页面中创建一个dom,支持使用canvas和svg两种渲染模式,进行预览

npm install --save pdfh5

<template>
  <div id="app">
	<div id="demo"></div>
  </div>
</template>
<script>
  import Pdfh5 from "pdfh5";
  export default {
    name: 'App',
	data() {
	  return {
	    pdfh5: null
	  };
	},
	mounted() {
		//实例化
	  this.pdfh5 = new Pdfh5("#demo", {
		pdfurl: "../../static/test.pdf"
	  });
	  //监听完成事件
	  this.pdfh5.on("complete", function (status, msg, time) {
		console.log("状态:" + status + ",信息:" + msg + ",耗时:" + time + "毫秒,总页数:" + this.totalNum)
	  })
	}
  }
</script>


//*********************************或者js引入****************************
//1.引入css
<link rel="stylesheet" href="css/pdfh5.css" />
//2.创建div
<div id="demo"></div>
//3.依次引入js
<script src="js/pdf.js" type="text/javascript" charset="utf-8"></script>
<script src="js/pdf.worker.js" type="text/javascript" charset="utf-8"></script>
<script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script>
<script src="js/pdfh5.js" type="text/javascript" charset="utf-8"></script>
//4.实例化
var pdfh5 = new Pdfh5('#demo', {
  pdfurl: "./default.pdf"
});

12.ios微信首次打开h5页面,底部是没有历史记录导航的,如果这时候直接跳转外链,再返回,这时首页底部就会增加历史记录导航,而且出现的问题是》》》》遮挡首页底部部分内容(商城首页)

解决办法:
手动增加一个空的历史记录

/**
 * 判断是否为ios
 */
export function isIOS () {
  return !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
}
/**
 * 微信浏览器判断
 */
export function isWXBrowser () {
  var ua = window.navigator.userAgent.toLowerCase()
  if (ua.match(/MicroMessenger/i) == 'micromessenger') return true
  return false
}

 if (isIOS() && isWXBrowser()) {
      window.history.pushState({}, '', '')
    }

13.苹果iOS11,iphoneX以上存在安全区域兼容适配

事故源自于一次App中内嵌H5网页,h5页面底部出现一条灰色的空白区域,当底部弹出选择框时,被这个灰条挡住下面的一部分,考虑是iphoneX机型,故可认定为安全区域的阻挡,同样的,在iphone6机型中就无此问题。
解决办法:
在html文件中设置头部的meta,viewport-fit设置为cover

<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">

在被遮挡的弹出层上设置

padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */

因为项目是老项目,设计到的页面比较多,故没有全局的body去设置,哪个页面出现问题就用这个办法去解决。但是移动端新的项目在做开始的适配的时候,建议全局设置safe-area-inset-bottom

14.ios在微信浏览器中的h5网页有页面的回弹效果,若页面中存在轮播的swiper组件,滑动过程中会出现页面抖动

话说这个问题我找了好久,开始还以为是偶现问题,后来一顿操作排除发现不太对,这尼玛只要你滑到底部,手暂停一下不松手,页面的抖动就出现了,而这个抖动和轮播下一张图片是一起出现,故定位到了问题的根本所在!!!
解决办法: 监听页面的滑动事件,在滑动触发的时候,停止轮播的动画,OK~~ fine next!

15.offsetLeft和offsetTop的使用

offsetLeft值跟offsetTop值的获取跟父级元素没关系,而是跟其上一级的定位元素(除position:static;外的所有定位如fixed,relative,absolute)有关系,是距离上一个使用定位元素的距离

16.scrollTo(0,0)和scrollTop=0

苹果低版本的手机上不支持获取使用dom.scrollTo(0,0),使用该方法会报错。
换言之,使用dom.scrollTop=0,就可以正常使用

17.app内嵌H5,当app在后运行时,h5页面的所有js进程都会被停止。

比如当我在内嵌的H5页面写一个定时器时,当我回到桌面,(这里并非是杀掉app,而是后台运行app),定时器就会暂时停止。只有当我回到app里面,定时器就会接着刚才的进程继续打印(这里并非是从头执行,而是接着执行)

18.移动端文字实现两端对齐,使用text-align-last在ios会有兼容性问题

使用text-align-last:justify;在安卓上面表现没有问题,但是在ios上面不会对齐。
解决办法:在当前的元素后面添加一个after伪类,并给当前的元素设置行高为0,如下:

span{
	text-align: justify;
    text-align-last: justify;
	line-height:0px;
	&::after{
		content:"";
	    width:100%;
	    display:inline-block;
	}
}

如此,安卓和ios都可以很好的兼容

19.移动端安卓和ios对于格式化时间new Date()日期格式的处理兼容性问题

const strTime="2018-1-1 9:10:10";
const myDate = new Date(strTime);
const Y = myDate.getFullYear();
const M = myDate.getMonth()+1;
const D = myDate.getDate();
const curDay = Y + '-'+ M + '-' + D;
console.log(curDay)
// 输出结果:Android系统:2018-1-1           iOS 系统:NaN-NaN-NaN 

明显ios对于格式化时间new Date()的不兼容
解决办法:

const strTime="2018-1-1 9:10:10";
var date= new Date(Date.parse(strTime.replace(/-/g,  "/")));  //转换成Data(); 

使用字符串的替换,将 ”-“替换为 ”/“,这样ios和安卓就都可以支持了

20.安卓和ios在调用微信的jssdk的时候的区别,批量隐藏\显示菜单时灵时不灵问题

安卓:当你在当前页面使用wx.hideMenuItems(),会把你想要隐藏的菜单隐藏起来,当你跳转到新的页面时(也就是重新调用wx.config后),你的隐藏了的菜单又会被重新显示出来,需要重新调用wx.hideMenuItems(),再次把你想要隐藏的菜单隐藏起来
ios:当你在当前页面使用wx.hideMenuItems(),会把你想要隐藏的菜单隐藏起来,当你跳转到新的页面时(也就是重新调用wx.config后),你在上一个页面隐藏的菜单还会继续保持隐藏的状态。如果这个时候你想让之前隐藏的菜单展示出来,就必须调用 wx.showMenuItems() 方法去设置要显示出来的菜单,才能实现这个需求

其他端兼容性问题总结:

1.在当前页面(这里指的pc端)使用iframe嵌套其他域名下的子页面时,父子页面跨域通信,使用postMessage方法,第一次调用会执行一次,第二次会执行两次,第三次会执行三次……

解决iframe父子跨域postMessage进行通信时,开始我使用的监听方式是window.addEventListener(‘message’, (e) =>{ });监听到的message事件就会有多次触发的场景。
后面网上查询,没有找到很明确的解释。但大概意思就是多次调用addEventListener(‘message’, (e) =>{ })会生成多次不同的匿名函数e,后面每一次调用这个监听方法,就触发前几次生成的匿名函数,而且匿名函数的数据都是前几次的旧数据,不会被新数据更新。有点类似于生成了一种旧数据缓存的机制。
解决这种现象:
使用window.onmessage=function(e) { };对message事件进行监听就可以了,就酱~~~

2.html2canvas 在ios15系统中生成海报图片的过程中含有页面空白问题

html2canvas 生成海报的时候,含有中文的元素在ios15系统上直接白屏生成失败,经过排查,去原仓库下面提issue后发现是ios15系统字体的问题,给中文字体设置如下字体可解决:

.text{
 font-family: Helvetica, Tahoma, Arial, 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC', STXihei, 'Microsoft YaHei', SimHei;
}
<think>好的,我现在需要帮助用户解决如何将扫枪与Vue.js集成的问题。首先,我得回忆一下用户提供的引用内容。引用[2]提到了uniapp实现扫枪扫,可能涉及到监听输入事件。而引用[1]是关于Electron和serialport的安装,不过用户现在用的是Vue.js,可能不直接相关,但如果是桌面应用可能需要串口库。 用户的需求是Vue.js对接扫枪,所以需要明确扫枪的工作方式。通常扫枪模拟键盘输入,输入完成后有结束符如回车或Tab。所以关键点在于监听输入事件,并区分是手动输入还是扫枪输入。 接下来,我需要分步骤思考实现方法。首先,在Vue组件中创建一个输入框,并监听键盘事件。然后,需要识别扫枪的输入特征,比如快速输入和结束符。可能需要定时器来判断输入间隔,以区分手动输入和扫枪的快速输入。 然后,需要处理数据,比如去除结束符,并触发相应的业务逻辑,比如提交数据或调用API。此外,可能需要处理多个输入框的情况,自动切换焦点,提升用户体验。 还要考虑不同的扫枪配置,有的可能不发送结束符,这时候需要其他方法,比如监听特定字符长度或使用串口通信,但这种情况可能需要额外的库,如serialport,这在浏览器中可能不可行,除非使用Electron或Node.js后端。但用户问的是Vue.js,所以主要聚焦于浏览器端的实现。 最后,需要提供示例代,展示如何在Vue组件中实现这些逻辑,并给出优化建议,比如防抖、自动焦点切换等。同时,要提醒用户测试不同设备和扫枪配置,确保兼容性。</think>以下是使用Vue.js对接扫枪的实现方法与示例教程: --- ### 一、扫枪工作原理 扫枪本质是模拟键盘输入设备,扫后会向系统发送字符流并以特定结束符(通常为回车/Tab)结尾。浏览器中可通过监听输入事件捕获数据[^2]。 --- ### 二、Vue.js实现步骤 #### 1. 创建输入监听组件 ```vue <template> <div> <input ref="scannerInput" v-model="scanData" @keyup.enter="handleScan" placeholder="请扫..." /> </div> </template> <script> export default { data() { return { scanData: '', lastInputTime: 0 } }, methods: { handleScan(e) { // 通过时间间隔判断是否为扫(通常<100ms) const currentTime = Date.now(); if (currentTime - this.lastInputTime > 100) { this.scanData = ''; // 重置数据 } this.scanData = e.target.value.trim(); this.lastInputTime = currentTime; // 提交扫结果 this.$emit('scan-complete', this.scanData); // 自动清空输入框 this.$nextTick(() => { this.scanData = ''; this.$refs.scannerInput.focus(); }); } }, mounted() { this.$refs.scannerInput.focus(); } } </script> ``` #### 2. 高级优化方案 ```javascript // 添加防抖处理 import { debounce } from 'lodash'; export default { methods: { handleScan: debounce(function(e) { const rawData = e.target.value; if (this.isValidBarcode(rawData)) { // 自定义校验逻辑 console.log('有效扫:', rawData); } }, 200) } } ``` --- ### 三、关键实现细节 1. **自动聚焦** 使用`this.$refs.scannerInput.focus()`保持输入框持续聚焦 2. **结束符处理** 通过`@keyup.enter`监听回车结束符,部分设备可配置为Tab键 3. **输入防抖** 使用Lodash的debounce避免重复触发(建议150-300ms间隔) 4. **多输入框场景** 可通过监听`document.addEventListener('keypress')`全局事件,配合自动切换焦点 --- ### 四、特殊设备对接 对于需要串口通信的工业扫枪: 1. 使用Electron构建桌面应用 2. 通过`serialport`库进行通信: ```javascript npm install serialport // 需要Node.js环境[^1] ``` --- ### 五、测试注意事项 1. 不同品牌扫枪的结束符配置 2. 中文输入法兼容性 3. 移动端浏览器的键盘弹出问题 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值