mpVue 开发小程序总结

1,748 阅读3分钟

开始踩坑

未做过小程序开发,但是使用过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
              });
            }
          });
        }
      });
    },

结语

目前遇到的坑不太多,会继续找坑往里跳^_^。