# mpvue 使用

app.vue & main.js
┌---------┐                            ┌----------┐   ┌---------┐
| app.vue ├--┐                         | app.js   |   | app.json|
└---------┘  |                         └----------┘   └---------┘
             ├---------------------->
┌---------┐  |     webpack             ┌----------┐
| main.js ├--┘                         | app.wxss |
└---------┘                            └----------┘


page.vue & main.js
      ┌------------------------------┐
┌-----┴-----┐      ┌-------┐         |
| page.vue  ├----> | .sass |         |
└---┬-┬-┬---┘      └-------┘         |
    | | |                            |
    | | |     ┌------------┐         |
    | | └---> | common.css |         |                 ┌-------┐  ┌-------┐
    | |       └-------┬----┘         v                 |  .js  |  | .json |
    | |               |        ┌---------┐             └-------┘  └-------┘
    | |   ┌------┐    |        | main.js ├----------->
    | └-->| .js  |    v        └---------┘   webpack   ┌-------┐  ┌-------┐
    |     └------┘  ┌-------┐                          | .wxml |  | .wxss |
    |     ┌------┐  | .font |                          └-------┘  └-------┘
    └---->| .jpg |  └-------┘
          └------┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

除了 Vue 本身的生命周期外,mpvue 还兼容了小程序生命周期,这部分生命周期钩子的来源于微信小程序的 Page, 除特殊情况外,不建议使用小程序的生命周期钩子

  • app 部分:
onLaunch,初始化
onShow,当小程序启动,或从后台进入前台显示
onHide,当小程序从前台进入后台
1
2
3
  • page 部分:
onLoad,监听页面加载
onShow,监听页面显示
onReady,监听页面初次渲染完成
onHide,监听页面隐藏
onUnload,监听页面卸载
onPullDownRefresh,监听用户下拉动作
onReachBottom,页面上拉触底事件的处理函数
onShareAppMessage,用户点击右上角分享
onPageScroll,页面滚动
onTabItemTap, 当前是 tab 页时,点击 tab 时触发 (mpvue 0.0.16 支持)
1
2
3
4
5
6
7
8
9
10
  • 不支持在组件上使用 Class 与 Style 绑定

  • 嵌套列表渲染,必须指定不同的索引!

  • 原生事件也可以使用例如 bindregionchange 事件直接在 dom 上将 bind 改为 @, @regionchange;

  • 如何获取小程序在 page onLoad 时候传递的 options

    • 在所有 页面 的组件内可以通过 this.$root.$mp.query进行获取
  • 如何获取小程序在 app onLaunch/onShow 时候传递的 options

    • 在所有的组件内可以通过 this.$root.$mp.appOptions 进行获取。
  • 如何捕获 app 的 onError

    • 在 app 的根组件上添加名为 onError 的回调函数
      // 只有 app 才会有 onLaunch 的生命周期
       onLaunch () {
           // ...
       },
      
       // 捕获 app error
       onError (err) {
           console.log(err)
       }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
  • v-html 指令不能用

  • 不支持部分复杂的 JavaScript 渲染表达式

  • 不支持过滤器

  • 不支持在 template 内使用 methods 中的函数

  • 不支持 classObject 和 styleObject 语法

  • mpvue 可以支持小程序的原生组件,比如: picker,map 等,需要注意的是原生组件上的事件绑定,需要以 vue 的事件绑定语法来绑定,如 bindchange="eventName"事件,需要写成 @change="eventName"

  • 合理使用双向绑定 mpvue 建议使用 v-model.lazy 绑定方式以优化性能

  • 新增的页面需要重新 npm run dev 来进行编译

  • 在触发事件后如果要获取对应的值,需要写成这样: e.mp.detail.value

# install

npm i -g @vue/cli-init

vue init mpvue/mpvue-quickstart my-wx

cd my-wx
 
npm install

npm run dev
1
2
3
4
5
6
7
8
9

# 全局 API

   // 调用API从本地缓存中获取数据
    /*
     * 平台 api 差异的处理方式:  api 方法统一挂载到 mpvue 名称空间, 平台判断通过 mpvuePlatform 特征字符串
     * 微信:mpvue === wx, mpvuePlatform === 'wx'
     * 头条:mpvue === tt, mpvuePlatform === 'tt'
     * 百度:mpvue === swan, mpvuePlatform === 'swan'
     * 支付宝(蚂蚁):mpvue === my, mpvuePlatform === 'my'
     */

在 mpvue 中调用 wx 的API

如:
wx.canIUse('button.open-type.getUserInfo')    ==>  mpvue.canIUse('button.open-type.getUserInfo')



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 获取手机号

<van-button type="primary" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">获取手机号</van-button>

getPhoneNumber (e) {
    mpvue.checkSession({
      success () {
        // session_key 未过期,并且在本生命周期一直有效
        console.log(e)
      },
      fail () {
        // session_key 已经失效,需要重新执行登录流程
        mpvue.login() // 重新登录
      }
    })
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14

注意:
在回调中调用 wx.login 登录,可能会刷新登录态。此时服务器使用 code 换取的 sessionKey 不是加密时使用的 sessionKey,导致解密失败。
建议开发者提前进行 login;或者在回调中先使用 checkSession 进行登录态检查,避免 login 刷新登录态

# mpvue引入vant Weapp样式的时候,没有把原来的px转换成rpx,应该是px2rpx插件的配置有问题

最后用transform在copy的时候解决掉
var Px2rpx = require('px2rpx');
var px2rpxIns = new Px2rpx({ rpxUnit: 0.5 });

// copy custom static assets
new CopyWebpackPlugin([
  {
    from: path.resolve(__dirname, '../static'),
    to: config.build.assetsSubDirectory,
    transform(content, path) {
      if (path.endsWith('.wxss')) {
        return px2rpxIns.generaterpx(content.toString(), 1)
      } else {
        return content
      }
    },
    ignore: ['.*']
  }
]),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# mpvue 配置less后 提示报错信息UnhandledPromiseRejectionWarning: TypeError: loaderContext.getResolve is not a function

# 卸载less-loader
# 重新安装指定版本
因为当时 mpvue 中使用的webpack 是 "webpack": "^3.11.0", 最开始安装  "less-loader": "^7.2.1",版本比较高

npm i --save less-loader@4.1.0

解决
1
2
3
4
5
6
7

# mpvue 中使用ECharts

npm i mpvue-echarts echarts --save


<template>
  <div class="echarts-wrap">
    <mpvue-echarts :echarts="echarts" :onInit="onInit" canvasId="demo-canvas" />
  </div>
</template>

<script>
import * as echarts from 'echarts/dist/echarts.min'
import mpvueEcharts from 'mpvue-echarts'

let chart = null;

function initChart(canvas, width, height) {
  chart = echarts.init(canvas, null, {
    width: width,
    height: height
  });
  canvas.setChart(chart);

  var option = {  // ECharts 配置项
    xAxis: {
      type: 'category',
      data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
    },
    yAxis: {
      x: 'center',
      type: 'value',
      splitLine: {
        lineStyle: {
          type: 'dashed'
        }
      }
    },
    series: [{
      name: 'A',
      type: 'line',
      smooth: true,
      data: [18, 36, 65, 30, 78, 40, 33]
    }, {
      name: 'B',
      type: 'line',
      smooth: true,
      data: [12, 50, 51, 35, 70, 30, 20]
    }]
  };

  chart.setOption(option);

  return chart; // 返回 chart 后可以自动绑定触摸操作
}

export default {
  components: {
    mpvueEcharts
  },
  data () {
    return {
      echarts,
      onInit: initChart
    }
  }
}
</script>

<style scoped>
.echarts-wrap {
  width: 100%;
  height: 300px;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

# 第三方的网络请求库 fly

npm install flyio   ||   cnpm install flyio

# 引入

import Fly from "flyio/dist/npm/wx";

# 1. 创建一个 fly 实例

let fly = new Fly;

# 2. 发起GET请求

// 通过用户id获取信息,参数直接写在url中
fly.get('/user?id=133')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

// query参数通过对象传递
fly.get('/user', {
      id: 133
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
  
  
# 3. 发起POST请求

fly.post('/user', {
    name: 'Doris',
    age: 24
    phone:"18513222525"
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
  
  
# 4. 发起多个并发请求

function getUserRecords() {
  return fly.get('/user/133/records');
}

function getUserProjects() {
  return fly.get('/user/133/projects');
}

fly.all([getUserRecords(), getUserProjects()])
  .then(fly.spread(function (records, projects) {
    //两个请求都完成
  }))
  .catch(function(error){
    console.log(error)
  })
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

# 图片预加载

npm install mpvue-img-load

<div>
  <image v-if="imgUrl" :src="imgUrl" />
  <img-load ref="imgLoad"></img-load>
</div>
  import imgLoad from 'mpvue-img-load'

  export default {
    data () {
      return {
        imgUrl: ''
      }
    },
    components: {
      imgLoad
    },
    methods: {
      loadImage () {
        // 加载缩略图 80x50 3KB
        this.imgUrl = 'http://storage.360buyimg.com/mtd/home/lion1483683731203.jpg'
        // 原图 3200x2000 1.6MB
        const imgUrlOriginal = 'http://storage.360buyimg.com/mtd/home/lion1483624894660.jpg'
        // 同时对原图进行预加载,加载成功后再替换
        this.$refs.imgLoad.load(imgUrlOriginal, (err, data) => {
          if (!err) {
            this.imgUrl = data.src
          }
        })
      }
    },
    mounted () {
      this.loadImage()
    }
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 参考