?移动端常见错误处理?持续更新

?移动端常见错误处理,项目还在继续迭代,所以会持续更新常见的问题以及处理办法。
这个是项目简介:
好单库cms

文字中出现未知字符

image.png

测试在ios13.7的微信上出现,chrom、dege、安卓均无法复现,一开始推测是数据中存在不识别的字符,但是在dege的控制台下看到文本前啥也没有。

image.png

这就怪了,嘛呢,艹。最后发现这个问题可以在ie上复现,直接在ie控制台输入这条记录

image.png

这狗东西前面确实有东西,但不知道具体是什么。无赖之下对他进行编码看看

decodeURIComponent(res.itemshorttitle)
// '%EF%B8%8FISDE%E6%97%A5%E6%9C%AC%E8%BF%9B%E5%8F%A3dite%E9%85%B5%E7%B4%A0120*2'
复制代码

结果显示多出来的这个东西是 %EF%B8%8F, 这尼玛是个什么玩意,在单独对他进行解码看看

encodeURIComponent('%EF%B8%8F') // ''
复制代码

啥也没有,嘛呢,艹。行吧,那就直接字符串替换了。

const e = decodeURIComponent(res.itemshorttitle).replace('%EF%B8%8F', '')
encodeURIComponent(e)
复制代码

html2canvas合成的base64的图片无法长按保存

主要出现在一些较老的机型或较老的手机浏览器中,微信中正常。用小米mix3测试无论自带浏览器还是第三方浏览器(火狐、chrome、qq浏览器、夸克浏览器)均可以正常长按保存,但是在edge浏览器中,却不行,长按只出现分享,没有保存下载。一开始怀疑是不是edge的问题,然后测试了两张base64的图,一张可以,一张不行,这就说明是图的问题。可以合成base64图片的逻辑完全一样,有差别的应该就是大小了,对了验证,先看看不能保存的图片大小,高达4m,而正常保存的图片大小是1.2m,看来是大小的问题了。接着将不能保存的base64图片改小到1.8m,测试也可以长按保存,在经过反复验证,得到的结果是:超过2.2m就不行,最好控制在2m以内

html2canvas 截图不完整

表现为上部空白,只有一半的内容,其实不算是不完整,应该是偏移严重了,超出的就空白了。验证出现的情况是有滚动条且发生滚动后,当页面处于顶部时,截图正常,由此断定滚动条的锅,这下好搞了,解决思路就是,找到需要截图的dom,获取它距离顶部的偏移量在加上滚动条距离顶部的偏移量。

const domTop = (this.$refs.imageWrapper as HTMLElement).getBoundingClientRect().top + (document.scrollingElement as any).scrollTop
html2canvas(
    this.$refs.imageWrapper as HTMLElement,
    {useCORS: true, y: domTop, scale: 4}
).then(canvas => {
      const dataURL = canvas.toDataURL('image/png')
      console.log(dataURL)
})
复制代码

html2canvas 背景变黑色

小伙子,莫要忘了设置背景色呀

html2canvas(this.$refs.imageWrapper as HTMLElement, {background: '#fff'}).then()
复制代码

解决 Cannot find name ‘ClipboardItem’

找不到名称“ClipboardItem”,原生浏览器剪切板api,使用时触发这个报错,同样在shims-vue.d.ts文件下,添加一下代码:

declare class ClipboardItem {
  constructor(data: { [mimeType: string]: Blob })
}
// new ClipboardItem
new window['ClipboardItem']({
    [blob.type]: blob
})
复制代码

qrcodejs2 检查报错没有声明文件

项目使用ts,引入qrcodejs2后,一直报错,提示没有ts类型声明的文件,这个库比较老了,官方也没提供ts的声明文件,故而报错,针对这种情况,需要自己添加声明,在src目录下找到shims-vue.d.ts文件,添加一下代码:

declare module 'qrcodejs2'
复制代码

qrcodejs2生成的二维码在手机上无法设置大小

分享页面需要生产二维码, 选用了qrcodejs2库,按照200 * 200的比例生成正方形二维码。因为是移动端页面,页面布局使用rem,实际显示二维码的区域为90*90。

// 生成二维码
<div ref="qrcode"></div> // 宽高设置为90px
new QRCode(this.$refs.qrcode, {
    text: url,
    width: 200,
    height: 200,
    colorDark: '#000000',
    colorLight: '#ffffff',
    correctLevel: QRCode.CorrectLevel.H
})
复制代码

生成完毕后,在ref=”qrcode”节点内部创建了img和canvas两个节点,默认下canvas是隐藏的,只显示图片。接下来对图片设置宽高100%来贴合父元素。到此pc上显示正常。手机端却出现二维码显示异常,大小直接就是200 * 200,超出了父元素。人直接傻掉了,艹 。手机浏览器在这么怪,也不至于宽高设置直接无效吧,直接祭出vconsole,得到的结果我直接艹了。手机渲染的节点与pc完全相反:

  • 手机 默认canvas, img的src为空且隐藏
  • pc 默认img,src是base64, canvas隐藏

难改我设置宽高无效,哪里是无效,根本南辕北辙了,艹。

解决:将img隐藏,默认使用canvas,为canvas设置宽高100%来贴合父元素。

获取url上的参数

function getUrlParam (name, url) {
    const urlPar = url ? new URL(url) : window.location
    const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)')
    const r = urlPar.search.substr(1).match(reg)
    const h = urlPar.hash.split('?')[1]?urlPar.hash.split('?')[1].match(reg):null
    if (r != null) {
        return unescape(r[2])
    } else if (h != null) {
        return unescape(h[2])
    } else {
        return null
    }
}
使用方法:
getUrlParam('cid') // 不传入url读取location
getUrlParam('id', 'https://a.aaa.com/?id=2') // 2
getUrlParam('val', 'https://a.aaa.com/?id=2#/home?val=1') // 1
复制代码

部分安卓机无法显示1px的边框

项目中所有px单位都会被转换成rem,1px转换后变成0.03125rem,部分安卓机对于小于1px的无法显示。

border: 1PX solid red // 指定1px, 大写px不会被转换
复制代码

价格去掉多余的0

// 12.12 -> 12.12
// 12.10 -> 12.1
// 12.00 -> 12
parseFloat(price)
复制代码

ios定位不居中

用来表示选择的小横条,一般使用伪类+定位实现

position: absolute;
bottom: 0;
复制代码

通常情况下,它是左右居中的,但是ios它有自己的想法:

left: 0;
right: 0;
margin: 0 auto;
复制代码

ios横向滚动条隐藏

::-webkit-scrollbar
    display: none
复制代码

ios圆角多了一条未知横线

image.png

这个问题比较玄学,不知啥原因(有知道的大佬请告知下)。目前的解决办法有两个:

  • 对原来的高度多加1像素
  • 直接去掉元素高度

ios使用行级块布局时显示参差不齐

在父级未指定高度的情况下,所有子元素横向排列,在ios上出现参差不齐的状态

display: inline-block;
vertical-align: top; // 显式指定对齐方式
复制代码

ios文字渐变效果失效

一开始怀疑是background-clip: text属性在ios下存在兼容问题,去查下发现ios对它的支持非常好(caniuse),我的测试机型都是ios9,不可能是兼容问题。既不是兼容又会是啥,排查下来发现,是display: flex的问题,靠。。。

// display: flex;
display: inline-block;
复制代码

iframe嵌套页面无法跳转

项目中使用iframe来显示外链,方便给外链添加返回按钮。但是后来发现,iframe嵌套的页面中如果使用了window.location.href来跳转,会导致跳转失败,页面url地址也不会发生变化。解决可以使用
window.parent.location.href 或者 window.top.location.href。window.parent指向父级,通常为iframe,window.top指向跟级,通常为多个iframe的最外层。没有iframe时,window.parent==window.top==window

window.parent.location.href = ''
复制代码

windows环境验证在QQ中失效

我的验证函数

export const isWin = () => {
  return /Windows|Win/i.test(navigator.userAgent)
}
复制代码

使用QQ调试发现,QQ中navigator.userAgent的信息里包含有nMagicWin的字样,被判定为windows环境了

Mozilla/5.0 (Linux; Android 10; M2007J1SC Build/QKQ1.200419.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045614 Mobile Safari/537.36 V1_AND_SQ_8.7.5_1738_YYB_D A_8070510 QQ/8.7.5.5330 NetType/WIFI WebP/0.3.0 Pixel/1080 StatusBarHeight/91 SimpleUISwitch/0 QQTheme/1000 InMagicWin/0 StudyMode/0
复制代码

将Win标记删除,只使用Windows即可

export const isWin = () => {
  return /Windows/i.test(navigator.userAgent)
}
复制代码

better-scroll在ios 上切换后滚动失效

我是用better-scroll是在keep-alive页面中,切换到其他页面,组件不会销毁,ios在其他页面滑动时会在底部弹出前进、后退的按钮,返回到better-scroll的页面,会无法滚动,需要在activated钩子中重新计算滚动区域的高度。

activated() {
    if (this.bs) {
      this.bs.refresh()
    }
  }
复制代码

better-scroll判断上拉、下拉

// dom 滚动区域
this.bs.on('touchEnd', (str: BScrollStr) => {
        if (str.y > 60) {
          console.log('下拉了')
          return false
        }
        const tranY: number = (dom.scrollHeight - dom.clientHeight) * -1
        if (tranY - str.y > 60) {
          console.log('上拉了', tranY)
          return false
        }
})
复制代码

better-scroll上拉、下拉更新数据后无法点击

我的实际案例就是,左侧是导航按钮,右侧是滚动内容的区域,当点击导航按钮时,右侧的滚动区域数据要对应更新,对了能正确滚动,还需要重新计算滚动内容高度。滚动内容是不同的商品类别,是可以点击的,初始化时,需要添加click:true的属性。

this.bs = new BScroll(dom, {
    probeType: 3, // 实时派发scroll
    click: true // 响应click事件
})
复制代码

第一次初始化时,数据可以正常点击,点击侧边导航,更新数据,重新计算后,滚动正常,点击也正常,问题就出现在滑动更新数据后,click失效了,几次摸索,发现是在上拉、下拉的判定时触发更新数据的函数,虽然数据正常,滚动正常,但是旧的滚动没有被结束,导致click无法执行。找到问题就比较好解决了:

if (this.bs) {
    this.bs.stop() // 先停止滚动
    this.bs.destroy() // 在销毁绑定的事件
}
// 重新实例化
this.bs = new BScroll(dom, {
    probeType: 3,
    click: true
})
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享