开始踩坑
未做过小程序开发,但是使用过Vue开发移动端项目。目前公司需要做小程序项目,直接开撸mpvue。mpvue是使用vue开发小程序的前端框架,语法几乎一致,相比原生小程序开发要来得快
设置首页
为什么要设置首页?当你新增或修改了代码,想看看效果。小程序会重新编译,当你打开开发者工具看到的是首页,如果开发的页面是很深层的内页,那就尴尬了。 因此,开发过程中可以将你想看到的页面设置为首页。
mpvue 2.0 新版本修改:
app.json
pages: []
pages中第一个为首页。
mpvue 1.0 旧版本修改:
main.js
config: {
pages: [^]
}
pages中带^符号的为首页。
设置完首页,保存代码后,会直接跳入首页哦~
设置标题、下拉刷新
想为每个页面设置,那么在pages里都有main.js,因此新增:
export default {
config: {
navigationBarTitleText: '列表', //标题
enablePullDownRefresh: true, //是否下拉、上拉,
}
}
在vue里:
onPullDownRefresh(){
//刷新完成后关闭
wx.stopPullDownRefresh()
}
onReachBottom(){
this.page ++;
...
}
动态的设置小程序标题
onLoad(option){
let title = option.title ? option.title : '**'
wx.setNavigationBarTitle({
title: title
})
}
跳转方式
只能跳转到tabBar配置页面
wx.switchTab({
url: '/pages/index/index',
});
返回上一级页面(delta:返回的页面数,如果 delta 大于现有页面数,则返回到首页,默认值为1)
wx.navigateBack({
delta: 2
})
关闭当前页面,跳转到应用内的某个页面
wx.redirectTo({
url: '/pages/index/index',
});
保留当前页面,跳转到应用内的某个页面
wx.navigateTo({
url: '/pages/index/index',
});
关闭所有页面,打开到应用内的某个页面
wx.reLaunch({
url: '/pages/index/index'
})
页面传参
传出页面:
wx.navigateTo({
url: `/pages/index/main?id=${id}`
})
接收页面:
mounted(){
const id = this.$root.$mp.query.id
}
//or
onLoad(option) {
const id = option.id
}
简单得传参数可以如此,复杂参数的当然就用vuex了。
嵌套的webview
webview使用很简单
<web-view :src="src" ></web-view>
嵌套的页面上拉下拉居然有回弹,相当影响体验。因为嵌套的页面不需要滚动,因此直接禁用 touchmove 就好了。禁止网页下拉显示网页域名就解决了。慎用,有的页面需要touch事件。
在需要嵌套页面加上:
window.onload = function () {
document.body.addEventListener('touchmove', function (e) {
e.preventDefault()
//阻止默认的处理方式(阻止下拉滑动的效果)
}, {passive: false})
}
webview 上使用cover-view
当页面使用了webview时,小程序的webview会将页面自动撑满,并且覆盖掉其他组件。
想用标签覆盖怎么办
查看微信官方文档,cover-view, cover-image,是可以覆盖webview,且不支持其他标签。
开发过程中看不到cover-view的原因,我遇到的有两个(坑死)。
1.需要为cover-view设置css属性(必须)
.class{
position: fixed;
z-index: 999;//值你可以试,999是可行的
}
2.在微信开发者工具时,还是看不到cover-view的内容,但是不要认为是无效。可以使用预览或者真机查看,是有效果的。因此好的开发办法是,注释webview的代码,写好cover-view,再恢复webview的代码,在手机上查看最终结果。
官方有说过某些安卓手机不兼容的写法,延时show。
//v-if='webShow'
onShow(){
this.webShow = false;
setTimeout(()=> {
this.webShow = true
},200)
}
cover-view 不支持 :text-decoration: line-through;
可以写cover-view height:2rpx,通过positon:absolute 代替。
还遇到一个问题,在使用了cover-view页面,然后跳转到一个横屏页面,再返回。cover-view的定位会出现错误。比如本来是底部fixed,回来后在中间了。
解决办法:
和官方的解决安卓适兼容问题一样,
//css里同样
.class{
position: fixed;
z-index: 999;//值你可以试,999是可行的
}
//vue里
//<div :style={position} ></div>
onShow(){
this.webShow = false;
this.position = 'absolute'
setTimeout(()=> {
this.webShow = true;
this.position = 'fixed';
},200)
}
webview里H5跳转回小程序
首先引入
<script src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
判断是否为小程序
wx.miniProgram.getEnv( res => {
if (res.miniprogram) {
wx.miniProgram.navigateTo({ url: "/pages/***/main"})
} else {
//***
}
})
横屏,以及横屏适配
为某个页面设置横屏显示,在当前页面main.js中:
//设置
export default {
config: {
//"pageOrientation": "landscape",//固定横屏
//"pageOrientation":"auto",//用户旋转手机触发
}
}
//监听
onShow(){
wx.onWindowResize(res => {
if(res.deviceOrientation === 'landscape'){
//...
}else{
//...
}
})
}
这样页面就能横屏显示,但是问题出来了,因为小程序是用rpx布局,竖屏时根据设计图750的尺寸,750rpx对应了之前手机屏幕的宽,当横屏时750rpx相对手机屏幕的高。
在这种情况下,我们写的尺寸值会将页面放大。
横屏适配方案
1.使用px进行布局
px可以进行简单的适配,因为375px是占不满横屏的全屏。
2.使用vmin进行布局
vmax 相对于视口宽度或者宽度较大的那个。其中最大的那个被均分为100单位的vmax
vmin 相对于视口宽度或者宽度较小的那个。其中最大的那个被均分为100单位的vmin
因此,
当竖屏、横屏的时候,100vmin都是手机屏幕的宽,所以可以使用vmin来布局。
在使用rpx进行布局的时候,750rpx的取值为手机屏幕的宽,而在使用vim的时候,100vmin的取值为手机屏幕的宽度,所以rpx和vmin之间存在一个换算关系,即:x rpx = (x * 100/750)vmin。举个例子,750rpx = (750 * 100/750)vmin ,也就是750rpx = 100vmin。
所以,可以将rpx转化成vmin。
如果项目中使用到了scss进行布局,
//$rpx为需要转换的字号
@function tovmin($rpx){
@return #{$rpx*100/750}vmin
}
//使用
.class{
width: tovmin(750);
height: tovmin(750);
}
图片自适应高度
当想图片宽度100%,或者某一值,宽度height:auto时,小程序会默认给图片一个宽高,因此页面显示不是我们想要的高度auto的样子。
查看微信官方组件时:
可以将image标签的mode设置为widthFix,也就是缩放模式,宽度不变,高度自动变化,保持原图宽高比不变
<image mode='widthFix' src=''/>
获取微信信息、手机号授权
需要用户点击button获取,wx官方说是不能通过api获取了:
<!--手机号-->
<button v-if="!phoneNumber"open-type="getPhoneNumber "@getphonenumber="getPhoneNumber">手机号</button>
<!--微信信息-->
<button open-type="getUserInfo" lang="zh_CN" @getuserinfo="getUserInfo">微信信息</button>
首先需要调用
wx.login({
success(res){
//获取res.code
}
})
拿到res.code 和 button的 回调 获取的信息,请求后台的接口解密获取最终的用户信息。
小程序使用bindgetuserinfo、bindgetPhoneNumber,在mpvue里得将bind替换成@
微信支付
也需要调用wx.login
//第一步
wx.login({
success(res){
//获取res.code
...
}
})
//第二步
//通过code,以及后台需要的参数信息,请求后台接口(例如:下单后请求)
//获取微信支付所需要得参数res
//第三步
wx.requestPayment({
timeStamp: res.timeStamp,
nonceStr: res.nonceStr,
package: res.package,
signType: res.signType,
paySign: res.paySign,
success: res => {
...
},
fail: res => {
...
},
complete: res => {
...
}
})
保存网络图片到手机相册
首先获取图片相册权限,然后下载临时文件,最后保存至本地相册。
唯一需要注意的是,下载的临时文件要是微信后台配置的网络路径,https://.....
//防抖保存
saveImg: Debounce(function() {
let that = this;
wx.getSetting({
success: function(res) {
//不存在相册授权
if (!res.authSetting["scope.writePhotosAlbum"]) {
wx.authorize({
scope: "scope.writePhotosAlbum",
success: function() {
that.savePhoto();
},
fail: function() {
//拒绝后的操作,openSetting需要用户主动触发,所以可以放在showModal回调
// wx.showModal({
// title: "是否打开设置页面",
// content: "需要获取您的相册权限,请到设置中打开授权",
// success: res => {
// wx.openSetting({});
// }
// });
}
});
} else {
that.savePhoto();
}
}
});
}),
savePhoto() {
wx.showLoading({
title: "加载中" // 数据加载前loading
});
setTimeout(function() {
wx.hideLoading();
}, 2000);
let urlStr = '***';
var that = this;
wx.downloadFile({
url: urlStr,
success: function(res) {
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: function(data) {
wx.hideLoading();
wx.showToast({
title: "保存成功",
icon: "success",
duration: 1500
});
}
});
}
});
},
结语
目前遇到的坑不太多,会继续找坑往里跳^_^。