development

一、移动端300ms点击延迟

1、设置meta标签

1
<meta name="viewport" content="user-scalable=no">

缺点: 必须通过完全禁用缩放来达到去掉点击延迟的目的

2、设置meta标签 chrome(32版本以后)

1
<meta name="viewport" content="width=device-width">

3、CSS touch-actiontouch-action这个CSS属性。

如果将该属性值设置为touch-action: none,那么表示在该元素上的操作不会触发用户代理的任何默认行为,就无需进行300ms的延迟判断

4、FastClick

原理

FastClick就是在用户点击元素触发touchstart、touchmove、touchend分别冒泡到body元素时做了相关记录,并在touchend事件判断是否取消原生click由自己模拟click。我们自己做个简单版FastClick

使用

1
FastClick.attach(document.body);

无需设置:

  • FastClick是不会对PC浏览器添加监听事件

  • IE11+浏览器设置了css的属性touch-action: manipulation,它会在某些标签(a,button等)禁止双击事件,IE10的为-ms-touch-action: manipulation

边框1px

1、边框图片

1
2
border: 1px solid transparent;
border-image: url('./../../image/96.jpg') 2 repeat;

优点:没有副作用

缺点:border颜色变了就得重新制作图片;圆角会比较模糊

2、box-shadow

1
2
3
4
box-shadow: 0px  -1px 0px 0px #000, // 上边线
1px 0 0px 0px #000, // 右边线
0 1px 0px 0px #000, // 下边线
-1px 0 0px 0px #000; // 左边线

3、伪类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.setOnePx{
position: relative;
width: 100px;
height: 100px;
margin: 20px 10px;
}
.setOnePx:after{
position: absolute;
content: '';
background-color: #000;
display: block;
width: 100%;
height: 1px; /*no*/
transform: scale(1, 0.5);
top: 0;
left: 0;
}

跨域处理

简单请求

1、请求方法是 HEAD GET POST 之一

2、HTTP头信息不超出 Accept,Accept-Language, Content-Language, Last-Event-ID, Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain 几个字断

简单请求浏览器直接发出CORS请求。在头信息之中,增加一个Origin字段,表明本次请求来自哪个源(协议 + 域名 + 端口)

客户端

1
2
// 无需手动设置
Origin: http://domain.com

服务器

1
2
3
Access-Control-Allow-Origin: http://domain.com  // 可以用 * 允许所有,不设置无法访问
Access-Control-Allow-Credentials: true // 携带cookie
Access-Control-Expose-Headers: custom

CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma

如果想拿到其他或自定义字段,就必须在Access-Control-Expose-Headers里面指定

如果要发送Cookie

Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名

以koa配置为例子:

客户端:

1
2
3
4
5
6
7
8
9
10

const request = axios.create({
baseURL: '',
timeout: 20000,
headers: {
'Content-Type': 'application/json'
},
// 携带cookie凭证
withCredentials: true
})

服务端:

koa单个,多个域名允许跨域配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const cors = require('koa2-cors');

app.use(cors({
origin: function (ctx) {
// 可以直接用请求的origin,来实现所有借口都可跨域
// 也可以自己维护一个数组,按需添加
// 因为要携带 cookie 不能使用 *
// 域名结尾不能有 /
return ctx.header.origin;
},
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'], //设置获取其他自定义字段
maxAge: 5, // 指定本次预检请求的有效期,单位为秒, option 请求
Expires: new Date(Date.now() + 20000),
// 因为要携带 cookie 这里要配置为true
credentials: true,
allowMethods: ['GET', 'POST', 'DELETE', 'OPTION', 'PUT'],
allowHeaders: ['Content-Type', 'Authorization', 'Accept', 'Content-Length', 'credentials', 'X-Access-Token', 'Cache-Control', 'Pragma', 'X-Requested-With']
}));

非简单请求

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)

“预检”请求方法是OPTIONS,头信息里面,关键字段是Origin

解决方案

  • 代理服务器(nginx, 抓包工具,node中间键)

  • jsonp

  • 跨域资源共享(CORS)

  • postMessage跨域

  • location.hash + iframe跨域

懒加载设计思路

  • html解析时先加载一个站位图片,最后再用js选择性的加载真实图片

  • 如果需要滚动加载可以使用 Intersection Observer

  • 图片尺寸不确定引起的布局抖动问题我们可以设置 长宽比 来解决

ios 兼容

1、 ios input 失去焦点,因为软键盘顶起,没回到原位置,需手动滑一下

1
2
3
4
5
6
7
8
9
10
11
if (isIOS) {
const speed = 1
const timer = setInterval(() => {
var currentPosition = document.documentElement.scrollTop || document.body.scrollTop
currentPosition -= speed
window.scrollTo(0, currentPosition) // 页面向上滚动
currentPosition += speed // speed变量
window.scrollTo(0, currentPosition)// 页面向下滚动
clearInterval(timer)
}, 1)
}

2、ios new Date 问题

1
2
3
4
5
new Date('2019-01-11').getTime() 得不到正确的毫秒

采用 '/' 代替 '-'

new Date('2019/01/11').getTime()

h5 唤醒app

1、 点击打开app操作,如果有app直接打开,否则去下载,因为没有app唤醒回调,采用定时器作为回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
toApp () {
...
if (isIOS) {
if (window.$plt.platForm === 'wx') {
this.tips = true
} else {
const initialTime = new Date()
window.location.href = 'cherynewretail://' // Scheme
let waitTime = 0
this.setTime = setInterval(() => {
waitTime = new Date() - initialTime
if (waitTime > 2500) {
clearInterval(this.setTime)
window.location.href = 'https://apps.apple.com/cn/app/%E5%A5%87%E7%91%9E%E6%96%B0%E9%9B%B6%E5%94%AE/id1470033296' // 下载链接
}
}, 100)
}
}

ios 唤醒app后会继续跳到appstore

解决方案

监听h5 API visibilitychange ,浏览器标签隐藏或展示时触发 visibilitychange 事件

1
2
3
4
5
6
7
8
9
isHidden () {
if (document['hidden']) {
clearInterval(this.setTime)
}
}

created () {
document.addEventListener('visibilitychange', this.isHidden)
}

2、 app 内嵌 h5 左上角返回交互设计

h5页面是嵌入到app提供的webview中,难免会有直接从app跳转到h5页面的情况,当一个页面既可以从app直接跳转进入,也可以从其他h5界面点击进入的时候,点击左上角的返回的时候就需要进行入口判断,此时这个页面是从什么地方进入的。那我们的处理方案就是从app直接进入到页面中需要在url带一个参数,在点击左上角返回按钮的时候进行判断,如果存在这个参数 那么点击左上角直接退出,否则返回上一个页面

微信

第三方接入

微信公众平台

公众平台是微信号的一种,是在公众号中开发出更多功能

微信开放平台

开放平台是网站或app使用的接口平台,利用开放平台可在自己的网站或app上开发微信帐户登录、微信分享等功能!

1、 分享出去的图片,标题没有内容

可能的原因:微信公众号是否绑定了应用的域名、应该服务的ip是否加入了白名单、微信签名是否成功、appId是否正确。这个时候从这些配置中去定位找原因。

2、h5 在 ios 和 安卓中分享到朋友圈和好友和群里面

  • IOS中,打开页面继续分享,卡片的title,img显示异常,只会展示一个http链接;

  • 在微信朋友圈多次分享后,微信好友/微信群的多次分享显示的卡片信息异常,也是只展示一个http链接

对于hash路由,微信分享会对链接#前加入search,增加自己的标识符,如

  • 朋友圈:from=timeline&isappinstalled=0

  • 好友:from=singlemessage&isappinstalled=0

  • 微信群:from=groupmessage&isappinstalled=0

比如完整得地址为:https://domain.com/?from=timeline&isappinstalled=0#/home/index/333?shareType=true

链接中search不带有&的,分享正常:https://domian.com/?from=xxxx#/home/index/333?shareType=true

对于链接中search带有&的,分享异常:

https://domain.com/?from=timeline&isappinstalled=0#/home/index/333?shareType=true

解决方法:

通过分析,只需要将search后&的参数全部抹掉就可以解决
main.js中,在进入路由前时,对地址进行处理

1
2
3
4
5
6
7
8
let link = window.location.href
if(link.indexOf('&') > -1) {
let replaceStr = link.slice(link.indexOf('&'), link.indexOf('#'))
window.location.href = window.location.href.replace(
replaceStr,
''
);
}

3、分享版本问题

1
2
3
4
5
6
7
if(wx.onMenuShareAppMessage){ //微信文档中提到这两个接口即将弃用,故判断
wx.onMenuShareAppMessage(shareData);//1.0 分享到朋友
wx.onMenuShareTimeline(shareData);//1.0分享到朋友圈
}else{
wx.updateAppMessageShareData(shareData);//1.4 分享到朋友
wx.updateTimelineShareData(shareData);//1.4分享到朋友圈
}

4、微信静默授权的路由历史栈

问题:

在微信浏览器中进入支付页面,页面刷了一下,然后点击手机的返回按钮无法返回到上一页,总是停留在当前页。而普通浏览器则能够正常返回到上一页。

分析:

进入支付页面时,判断当前在微信环境的情况下,为了获取openid,会去请求微信内部鉴权地址进行微信静默授权,而授权后重定向到redirect_uri指定的地址会增加历史记录,redirect_uri指定一个中间页,这个中间页会把授权得到的code即openid增加到页面地址中然后location.replace到该页。所以,最后的历史记录栈为:下单前页面->无code下单页->有code下单页。点击返回的时候,返回到无code下单页,然后无code下单页又去请求授权,最后又跳到有code下单页,如此反复,陷入死循环。

解决方法:

授权成功后,在重定向的中间页中通过sessionStorage存储code,返回到无code下单页时判断code是否存在,如果存在则不再进行一系列授权操作。

5、 小程序 web-view 加载h5页面

src的url要进行 encodeURIComponent() 编码处理。

6、小程序上传和下载

小程序中上传文件和下载文件需要配置 downloadFile 合法域名 和 uploadFile 合法域名

7、webview 嵌入小程序无法分享

  • 因为小程序的手动转发需要通过<button type=”share”>实现,故无法在 webview 中唤起小程序的转发功能

  • 需要通过在h5页面点击唤起提示弹窗进行提示,提示用户通过右上角按钮进行操作转发分享

8、小程序中配置视频默认全屏播放会退不出来并且小程序卡住

由于统一管理的视频开始和暂停,在设置全屏的api时需要判断是否已经开启了全屏,否则会因为开启了多个全屏的 webview 而出现的 tabbar 消失,页面无法滚动等问题

9、小程序 webview 页面无法自定义顶部栏,故无法处理成全屏展示

10、小程序map穿透问题

需要使用 cover-view 但需要注意 cover-view 的子组件也必须是 cover 系列的

11、小程序真机调试 showtoast 不展示提示内容

  • 因为同时使用了showLoading 和 showToast,两者调用的是同一个遮罩,在 loading 未隐藏前,无法唤起 toast 导致toast无效

  • 可在 hideloading 的回调函数中处理 showToast

12、生成小程序码分享后进入的页面参数对应不上

生成小程序码的参数限制长度只有32位,生成二维码前需要检查参数长度是否超出长度

超出后解决方案:

  • 找到对应后端出一个通用接口专用来存储小程序参数

  • 检查一下是否需要传递多个参数,若可以,通过缩减参数数量在一定程度上也能避免参数长度超出

13、小程序 webview 嵌入页面内容未更新(缓存)

1
webview 地址里 + `?r=${new Date()getTime()}`

14、小程序previewImage导致微信闪退

  • 目前某些机型不支持base64 图片的预览,需要将base64图片转存到本地,生成本地图片的url

编码(凡是乱码基本上是编码问题)

项目静态文件包含模板文件、图片和生成的html页面文件(其中有中文命名文件)。由于后期调整了很多页面,导致生成的静态文件变多,体积变大,导出到本地的zip文件基本上就是90M(里面一个没用的目录,占了一半大小),而后端限制了上传文件大小不超过50M,这就需要在自己电脑上先将这个zip文件解压,删除这个没用的目录,减小文件体积,再压缩成zip文件上传。结果,所有中文的文件名称出现乱码,由于加载包含中文乱码文件名的图片导致图片挂掉,CMS管理员在后台查看的包含中文的模板文件名称都是乱码。

分析:

  • Linux系统默认的文件名编码方式 UTF-8

  • Windows系统默认的文件名编码方式 GBK

经配合分析,后端在处理打包、压缩静态文件时使用的是GBK编码,导出zip文件到本地后,在Windows系统上解压、编辑,再压缩成zip文件并上传,解压后,由于linux默认的UTF-8编码和文件名的GBK编码不一致,无疑会出现中文乱码

html2canvas

1、 跨域

用html2canvas截图时,dom元素的图片需要能够跨域访问,若不能跨域访问的图片,无法捕捉到改图片导致该图片占位为空

若该图片写在 backgound-image 里,则把该图片放到 image 里,并给它加上支持跨域的属性 crossorigin="anonymous" 。使用new Image()也需加上crossorigin属性

2、 ios 中无法识别 iframe 内的二维码

在 iframe 中,监听二维码的 touchstart事件,通过 parent.postMessage 将图片 url 传递给主页面,在主页面进行展示二维码,然后在在主页面监听二维码的 touchend 事件取消主页面二维码的展示。

注意:主页面的二维码要么与 iframe 页面的二维码位置一致,要么可全屏展示,但需要将二维码的透明度改到最小,如:0.01(不能为 0,为 0 时微信环境下无法识别,视觉上你看到的是iframe的二维码,扫码实际是iframe 顶层的二维码)

3、部分安卓手机 qrcode 生成二维码无法生存图片

QRcode 生成二维码时默认会生成 canvas和 image,并将 canvas 隐藏,image展示,但部分安卓手机则没有第二步

将生成的 canvas 和 image 都隐藏,另写一个 image 放置在显示二维码的部位,通过将 canvas.toDataUrl 获取图片的 base64 码并整理成可显示的内容(如:data:image/png;base64,iVBORw0K…),并将该值赋给 image 的 src 属性

返回
顶部