?移动端常见错误处理,项目还在继续迭代,所以会持续更新常见的问题以及处理办法。
这个是项目简介:
好单库cms
文字中出现未知字符
测试在ios13.7的微信上出现,chrom、dege、安卓均无法复现,一开始推测是数据中存在不识别的字符,但是在dege的控制台下看到文本前啥也没有。
这就怪了,嘛呢,艹。最后发现这个问题可以在ie上复现,直接在ie控制台输入这条记录
这狗东西前面确实有东西,但不知道具体是什么。无赖之下对他进行编码看看
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圆角多了一条未知横线
这个问题比较玄学,不知啥原因(有知道的大佬请告知下)。目前的解决办法有两个:
- 对原来的高度多加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
})
复制代码