一、背景
前端第一次使用 Wepy 框架(Wepy 2) 开发小程序,把遇到的坑都罗列一遍,希望能给大家做个参考。
二、问题总结
1、this 和 事件对象(event)的指向
之所以提出这个问题是因为在我们遇到问题查阅资料时,把一些用原生或者其他框架写的代码应用到自己的代码中,如果出现问题,可以朝这个方向排查一下。
在 Wepy2 中,this.$wx 对应原生的 this,event.$wx 对应原生的 event。
2、代码上传到体验版请求头出现“Provisional headers are shown”
问题分析:在调试阶段和后端约定响应头增加字段“JWT-TOKEN”,字段名称变成了“jwt-token”导致字段值获取不到,接口没能正确返回。
解决方案:为了兼容调试和发布两种环境,把字段大小写两种情况都写一下,注意避免和其他字段冲突。
3、子组件传多个参数给父组件问题
问题分析:虽说 Wepy 是一款类似 Vue 语法的开发框架,但是在 Wepy2 中,子组件传多个参数给父组件时,父组件只能接收到最后一个参数,
解决方案:以对象的方式传给父组件
4、wx.getPhoneNumber() 接口在用户拒绝授权手机号返回的提示信息不同
iOS:'fail user deny'
Android: 'fail:user deny'
5、wx.getSystemInfo() 接口在 iPhone 11 系列手机上获取 model 信息有误("unknown<iPhone12,1>")
问题分析:目前苹果11上市后微信对苹果11还没有适配不能拿到 iPhone 11 标识
解决方案:通过判断“system”是“ios”且“model”为“unknown”来判断,也可以使用 “platform”,但是注意这个字段在微信开发者工具上是"devtools",需要多考虑一种情况,具体使用哪种可以根据实际情况来选择
接口在 iPhone 11 上的返回结果:
6、微信小程序自定义导航栏(navigationStyle: 'custom')
问题分析:微信开放了自定义导航栏的控制权,使得我们开发者可以自由的开发导航栏,但同时增加开发者们不得不兼容各种手机的负担。
解决方案:参考链接 需要注意对 iPhone 11 的兼容。
组件代码:如果需要可以直接 copy 到项目中使用(基于原生的项目需要稍作修改)。
<style lang="less">
@import '~@/styles/mixin.less';
.navbar {
width: 100%;
background-color: #fff;
position: fixed;
top: 0;
left: 0;
z-index: 999;
}
.navbar-con {
height: 40px;
position: relative;
.alignCenter;
}
.capsule {
margin-left: 10px;
height: 31px;
background: rgba(255, 255, 255, .5);
border: 1px solid rgba(151, 151, 151, 0.1);
border-radius: 25px;
.alignCenter;
&.noBorder {
border: none;
}
&__item {
width: 43px;
height: 34px;
position: relative;
.flexCenter;
&:nth-child(2):after {
content: '';
position: absolute;
top: 6.5px;
left: 0;
width: 1px;
height: 17px;
background: rgba(151, 151, 151, 0.1);
}
image {
width: 17px;
height: 17px;
}
}
}
.title {
width: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
.flexCenter;
.fontBasic(16px, #000);
}
.navBar-loader {
height: 18px;
width: 18px;
animation: loader-1-1 4.8s linear infinite;
display: inline-block;
margin-right: 4px;
vertical-align: middle;
}
@keyframes loader-1-1 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.navBar-loader .inner {
display: block;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
height: 18px;
width: 18px;
clip: rect(0, 18px, 18px, 9px);
animation: loader-1-2 1.2s linear infinite;
}
@keyframes loader-1-2 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(220deg);
}
}
.navBar-loader .inner:after {
content: '';
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
height: 18px;
width: 18px;
clip: rect(0, 18px, 18px, 9px);
border: 3px solid #ccc;
border-radius: 50%;
animation: loader-1-3 1.2s cubic-bezier(0.770, 0.000, 0.175, 1.000) infinite;
z-index: 1000;
box-sizing: border-box;
}
@keyframes loader-1-3 {
0% {
transform: rotate(-140deg);
}
50% {
transform: rotate(-160deg);
}
100% {
transform: rotate(140deg);
}
}
</style>
<template>
<div class="container">
<div class="navbar" style="height:{{systemInfo.navBarHeight}}px;background-color:{{bgColor}};">
<div style="height:{{systemInfo.statusBarHeight}}px"></div>
<div class="navbar-con" style="height:{{systemInfo.navBarHeight-systemInfo.statusBarHeight}}px">
<div class="capsule" :class="{noBorder:!(back&&home)}" wx:if="{{ back || home }}">
<div class="capsule__item" @tap="backstep" wx:if="{{back}}">
<image src="@/images/back.png" mode="widthFix" />
</div>
<div class="capsule__item" @tap="backHome" wx:if="{{home}}">
<image src="@/images/home.png" mode="widthFix" />
</div>
</div>
<div class="title" style="color:{{fontColor}};">
<div wx:if="{{loading}}" class="navBar-loader">
<div class="inner"></div>
</div>
<text>{{title}}</text>
</div>
</div>
</div>
<div style="height:{{systemInfo.navBarHeight}}px;"></div>
</div>
</template>
<script>
import wepy from '@wepy/core'
import store from '@/store'
import {
mapState
} from '@wepy/x'
wepy.component({
store,
props: {
title: {
type: String,
default: 'AIDerma'
},
bgColor: {
type: String,
default: '#ffffff'
},
fontColor: {
type: String,
default: '#000000'
},
back: {
type: Boolean,
default: false
},
home: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: false
}
},
computed: {
...mapState(['systemInfo'])
},
methods: {
backHome() {
wx.reLaunch({
url: '/pages/case/list'
})
},
backstep() {
wx.navigateBack({
delta: 1
})
}
}
})
</script>
获取不同类型手机的自定义 navBar 高度:
wx.getSystemInfo({ success: (res) => { let menuButtonInfo = wx.getMenuButtonBoundingClientRect() // 基础库 2.1.0 开始支持,低版本需做兼容处理。 let systemInfoObj = { statusBarHeight: res.statusBarHeight, // 时间、信号等工具栏的高度 windowHeight: res.windowHeight, // 可使用窗口的高度 navBarHeight: 0, // 自定义导航栏高度 contentHeight: 0 // 页面内容高度 } systemInfoObj.navBarHeight = menuButtonInfo.bottom + menuButtonInfo.top - res.statusBarHeight systemInfoObj.contentHeight = systemInfoObj.windowHeight - systemInfoObj.navBarHeight if (res.screenHeight / res.screenWidth > 2) { this.$options.store.commit('isIPXUpdate', true) } this.$options.store.commit('SystemInfoUpdate', systemInfoObj) }})
7、小程序 wx.getSystemInfo 获取 windowHeight 问题
问题分析:在一些设备下获取 windowHeight 不能准确得到对应的高度,总是拿到屏幕高度,一般第一次杀掉微信进程后第一次打开会有这个问题,并且安卓设备上易现。
解决方案(参考链接):
windowHeight 的定义:可使用窗口高度,即:屏幕高度(screenHeight) - 导航(tabbar)高度;
可以看出这个值取决于 tabbar 是否存在,为了保证 tabbar 显示后再取值,建议在生命周期的 onReady 钩子中调用接口 wx.getSystemInfo,如果我们配置了自定义导航栏(navigationStyle: 'custom'),屏幕高度和窗口高度是相等的,我们可以直接使用屏幕高度
8、页面内跳转点击无反应
问题分析:通过打印“getCurrentPages()”到控制台,可以发现这是微信小程序路由跳转的一个隐藏的坑,就是 wx.navigateTo 打开新页面,最多只能打开 10 个,超过 10 个之后就没反应,控制台也不会报错。
解决方案:页面深度最好不要超过10层(如果有,可以适当使用 wx.redirectTo() 进行跳转),如果页面上有回到首页按钮,使用 wx.reLaunch() 进行跳转。
9、Echarts 在微信小程序中实践(基于 Wepy)
占位
10、一些建议
- 由于小程序对代码包大小的限制(2M),建议把首屏图片放在本地其他都放在 CDN,必要时做一下图片的预加载。
- 建议还是一开始就做好分包准备