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 或原生开发
目录