mpvue 框架

使用 Vue.js 开发微信小程序的框架

问题

什么是 mpvue?它的工作原理和使用场景是什么?

解答

什么是 mpvue

mpvue 是美团开源的一个使用 Vue.js 开发微信小程序的前端框架。它让开发者可以用 Vue 的语法和开发习惯来编写小程序代码。

工作原理

mpvue 在编译时将 Vue 代码转换为小程序代码:

Vue 单文件组件 (.vue)

    mpvue 编译器

┌───────────────────┐
│  .wxml (模板)      │
│  .wxss (样式)      │
│  .js   (逻辑)      │
│  .json (配置)      │
└───────────────────┘

基本使用

项目结构:

├── src/
│   ├── pages/
│   │   └── index/
│   │       ├── index.vue    # 页面组件
│   │       └── main.js      # 页面入口
│   ├── components/          # 公共组件
│   ├── App.vue              # 应用根组件
│   └── main.js              # 应用入口
├── static/                  # 静态资源
└── package.json

页面组件示例:

<!-- src/pages/index/index.vue -->
<template>
  <div class="container">
    <p>{{ message }}</p>
    <button @click="handleClick">点击计数: {{ count }}</button>
    <ul>
      <li v-for="item in list" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello mpvue',
      count: 0,
      list: [
        { id: 1, name: '苹果' },
        { id: 2, name: '香蕉' }
      ]
    }
  },
  
  // 小程序生命周期
  onLoad() {
    console.log('页面加载')
  },
  
  onShow() {
    console.log('页面显示')
  },
  
  // Vue 生命周期同样可用
  mounted() {
    console.log('组件挂载完成')
  },
  
  methods: {
    handleClick() {
      this.count++
    }
  }
}
</script>

<style scoped>
.container {
  padding: 20px;
}
button {
  margin: 10px 0;
}
</style>

页面入口文件:

// src/pages/index/main.js
import Vue from 'vue'
import App from './index.vue'

// 创建 Vue 实例
const app = new Vue(App)

// 挂载应用
app.$mount()

生命周期对应关系

export default {
  // Vue 生命周期
  beforeCreate() {},
  created() {},
  beforeMount() {},
  mounted() {},
  beforeUpdate() {},
  updated() {},
  beforeDestroy() {},
  destroyed() {},
  
  // 小程序 App 生命周期(仅在 App.vue 中有效)
  onLaunch() {},      // 小程序初始化
  onShow() {},        // 小程序显示
  onHide() {},        // 小程序隐藏
  
  // 小程序 Page 生命周期
  onLoad() {},        // 页面加载
  onReady() {},       // 页面初次渲染完成
  onShow() {},        // 页面显示
  onHide() {},        // 页面隐藏
  onUnload() {},      // 页面卸载
  onPullDownRefresh() {},  // 下拉刷新
  onReachBottom() {},      // 上拉触底
  onShareAppMessage() {}   // 分享
}

与原生小程序的差异

// 1. 事件绑定
// 原生小程序
// <button bindtap="handleTap">点击</button>

// mpvue
// <button @click="handleTap">点击</button>

// 2. 数据绑定
// 原生小程序
// <view>{{ message }}</view>
// this.setData({ message: 'new value' })

// mpvue - 直接赋值即可
// <view>{{ message }}</view>
// this.message = 'new value'

// 3. 列表渲染
// 原生小程序
// <view wx:for="{{ list }}" wx:key="id">{{ item.name }}</view>

// mpvue
// <view v-for="item in list" :key="item.id">{{ item.name }}</view>

// 4. 条件渲染
// 原生小程序
// <view wx:if="{{ show }}">显示</view>

// mpvue
// <view v-if="show">显示</view>

使用限制

// 1. 不支持 v-html
// ❌ <div v-html="htmlContent"></div>

// 2. 不支持部分复杂表达式
// ❌ <div>{{ list.filter(i => i.active) }}</div>
// ✅ 使用 computed
computed: {
  activeList() {
    return this.list.filter(i => i.active)
  }
}

// 3. 事件不能使用复杂参数
// ❌ <button @click="handleClick(item)">
// ✅ 使用 data-* 传参
// <button @click="handleClick" :data-item="item">

methods: {
  handleClick(e) {
    const item = e.currentTarget.dataset.item
  }
}

// 4. 不支持 filter
// ❌ {{ date | formatDate }}
// ✅ 使用 methods 或 computed

状态管理(Vuex)

// src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    userInfo: null,
    cartList: []
  },
  
  mutations: {
    SET_USER_INFO(state, info) {
      state.userInfo = info
    },
    ADD_TO_CART(state, item) {
      state.cartList.push(item)
    }
  },
  
  actions: {
    async login({ commit }, params) {
      // 调用登录接口
      const res = await wx.login()
      commit('SET_USER_INFO', res.userInfo)
    }
  }
})
<!-- 在组件中使用 -->
<template>
  <div>
    <p>用户:{{ userInfo.name }}</p>
    <p>购物车:{{ cartList.length }} 件</p>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'

export default {
  computed: {
    ...mapState(['userInfo', 'cartList'])
  },
  methods: {
    ...mapMutations(['ADD_TO_CART'])
  }
}
</script>

关键点

  • 编译转换:将 Vue 单文件组件编译为小程序的四个文件(wxml/wxss/js/json)
  • 语法兼容:支持 Vue 大部分语法,包括 v-if、v-for、@click 等
  • 双生命周期:同时支持 Vue 生命周期和小程序生命周期
  • 限制事项:不支持 v-html、filter,事件传参需用 dataset
  • 状态管理:可直接使用 Vuex 进行状态管理
  • 注意:mpvue 目前已停止维护,新项目建议使用 uni-app 或原生开发