当前位置:   article > 正文

微信小程序 之 mpvue

mpvue

一、mpvue ( Vue in Mini Program )

  • mpvue.com
  • 美团工程师推出的基于Vue封装的用于开发小程序的框架
  • 融合了原生小程序和Vue的特点
  • 组件化开发

二、初始化项目

1. 检查node和npm版本

node -v && npm -v

2. 安装vue-cli脚手架

npm install vue-cli -g

3. 创建mpvue项目

  1. vue init mpvue/mpvue-quickstart 项目名
  2. // 接下来可一路回车,后续可在project.config.json中进行配置

4. 进入改项目目录中,安装依赖

npm install

5. 在 project.config.json 配置 appid

appid : 在微信公众平台注册一个后,即可拥有

6. 执行,生成dist文件夹

npm run dev

因为这里是开发小程序,所以执行后并不会打开浏览器,因为没必要~,生成的dist文件夹才是我们所需要的 

7. 下载微信开发者工具

稳定版 Stable Build 更新日志 | 微信开放文档

8. 微信开发者工具打开改项目 ( 打开dist文件夹即可 ) 

9. 即可看到效果

三、mpvue中基本功能的使用

01. 全局配置文件 => app.json小程序配置 | 微信开放文档

02. 单个页面配置文件 => main.json

注 :单个页面的配置会覆盖全局配置

03. 单个页面挂载文件 => main.js

注 :在每个页面中都需要使用, 组件实例.$mount() 去挂载当前组件,否则对应的页面不能生效

但是,如果只是组件,那么可不写,直接引用,然后component注册即可使用

  1. // 导入vue
  2. import Vue from 'vue'
  3. // 导入组件
  4. import Index from './index.vue'
  5. // 生成一个vue实例
  6. const index = new Vue(Index)
  7. // 挂载到元素
  8. index.$mount()

04. 页面的样式

  1. <!-- //?模块说明 => 首页模块 -->
  2. <template>
  3. <div class='index-layout'>
  4. <div>index123</div>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. name: 'index'
  10. }
  11. </script>
  12. <style>
  13. /*
  14. 如果要设置整个页面样式(例如高度),需要在page中设置
  15. 每个页面都有一个page包裹着,相当于<page></page>
  16. */
  17. page {
  18. height: 100%;
  19. text-align: center;
  20. }
  21. /* 单纯设置这个是不会生效的 */
  22. .index-layout {
  23. height: 100%;
  24. background-color: #07c160;
  25. }
  26. </style>

05. 绑定方法 => 和vue中一样

06. 生命周期

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


四、mpvue中进阶功能的使用

01. 页面跳转

1 - 创建about组件,配置挂载组件main.js

2 - 在app.json中配置该页面

3 - 用 wx.navigateTo 跳转wx.navigateTo(Object object) | 微信开放文档

​​​​​​​在mpvue中对vue-router的支持不好,问题较多,页面跳转的是可使用小程序提供的API

  • wx.navigateTo()  保留当前页面,可回退
  • wx.redirectTo()  不保留,不能回退
  • wx.switchTab()  使用于tabBar页面

4 - 删除dist文件夹,重新执行 npm run dev 

注 : 如果是新建的页面,那么需要重新打包,否则会报错且不会生效

5 - 传递过程如果有参数传递

传递

  1. let data = {id : 1, name : '张三'}
  2. // id 和 data 即为传递的参数
  3. wx.navigateTo({
  4. url: '/pages/about/main?id='+data.id+'&data=' + JSON.stringify(data)
  5. })

接收 

  1. mounted(){
  2. console.log(this.$mp.query.id,JSON.parse(this.$mp.query.data));
  3. }

02. 使用vuex 

1. 下载vuex并在根目录中创建store文件夹

npm i vuex

2. 在store文件夹下创建index.js

  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. import state from './state.js'
  4. import mutations from './mutations.js'
  5. import actions from './actions.js'
  6. import getters from './getters.js'
  7. Vue.use(Vuex)
  8. const store = new Vuex.Store({
  9. state,
  10. mutations,
  11. actions,
  12. getters
  13. })
  14. export default store

3. 在store文件夹下创建state.js

  1. export default {
  2. // 初始化状态
  3. initName: 'star',
  4. initList: []
  5. }

4. 在store文件夹下创建actions.js

  1. export default {
  2. getList({
  3. commit
  4. }) {
  5. return new Promise((resolve, reject) => {
  6. // axios.get('/api/list').then(res => {
  7. // commit('setList', res.data);
  8. // resolve(res.data);
  9. // }).catch(err => {
  10. // reject(err);
  11. // })
  12. let bool = true
  13. let data = [{
  14. name: '张三',
  15. age: 18,
  16. }]
  17. if (bool) {
  18. commit('SET_LIST', data)
  19. resolve(data);
  20. }else{
  21. reject('error');
  22. }
  23. });
  24. }
  25. }

5. 在store文件夹下创建mutations.js 

  1. export default{
  2. // 获取列表数据
  3. SET_LIST(state, value) {
  4. // 赋值给state中的initList
  5. state.initList = value
  6. }
  7. }

6. store文件夹下创建getters.js 

  1. export default {
  2. // 拿到state中的initName数据
  3. getInitName: state => state.initName,
  4. }

7. 在入口文件main.js中导入

  1. import Vue from 'vue'
  2. import App from './App'
  3. import store from './store/index.js'
  4. // 将store挂载到Vue实例上,这样所有组件都可以使用store
  5. Vue.prototype.$store = store
  6. Vue.config.productionTip = false
  7. App.mpType = 'app'
  8. const app = new Vue(App)
  9. app.$mount()

8. 在组件中使用vuex 

  1. <!-- //?模块说明 => 首页模块 -->
  2. <template>
  3. <div class='index-layout' >
  4. <div @click="toAbout">跳转到about页面</div>
  5. </div>
  6. </template>
  7. <script>
  8. import {mapState, mapGetters,mapMutations,mapActions } from 'vuex'
  9. export default {
  10. name: 'index',
  11. computed:{
  12. // 使用mapGetters的getInitName方法获取初始化的initName值
  13. ...mapGetters(['getInitName']),
  14. // 使用mapState拿到initName的值
  15. ...mapState({
  16. initName: state => state.initName,
  17. initList: state => state.initList
  18. })
  19. },
  20. methods: {
  21. // 拿到mutations中定义的GET_LIST方法
  22. ...mapMutations(['SET_LIST']),
  23. // 拿到actions中定义的getList方法
  24. ...mapActions(['getList']),
  25. },
  26. mounted(){
  27. // 获取数据
  28. console.log(this.initName); //star
  29. console.log(this.getInitName); //star
  30. // 使用actions中定义的getList方法请求,获取数据
  31. // 相当于 this.$store.dispatch('getList');
  32. this.getList()
  33. console.log(this.initList); //{ name: '张三', age: 18}
  34. // 使用mutations中定义的SET_LIST方法设置数据
  35. // 相当于 this.$store.commit('SET_LIST', { name: '李四', age: 20 })
  36. this.SET_LIST({
  37. name: '李四',
  38. age: 20
  39. })
  40. console.log(this.initList); //{ name: '李四', age: 20}
  41. }
  42. }
  43. </script>
  44. <style>
  45. page {
  46. height: 100%;
  47. text-align: center;
  48. }
  49. .index-layout {
  50. height: 100%;
  51. background-color: #07c160;
  52. }
  53. </style>

03. 使用本地存储 

  1. // 需要存储的内容。只支持原生类型、Date、及能够通过JSON.stringify序列化的对象。
  2. wx.setStorageSync('key', 'value')
  3. // 获取
  4. wx.getStorageSync('key')

04. 微信提示 

  1. wx.showToast({
  2. title: '请求失败,请检查网络',
  3. icon: 'none'
  4. });

05. 设置小程序title 

1. 调用方法

  1. wx.setNavigationBarTitle({
  2. title: '哈哈哈'
  3. });

2. 在main.json中 

  1. {
  2. "navigationBarTitleText": "哈哈哈"
  3. }

06. 分享页面 wx.showActionSheet(Object object) | 微信开放文档

  1. share() {
  2. wx.showActionSheet({
  3. itemList: ['A', 'B', 'C'],
  4. success(res) {
  5. console.log(res.tapIndex)
  6. },
  7. fail(res) {
  8. console.log(res.errMsg)
  9. }
  10. })
  11. }

三、开始开发项目微信开放文档

1. 获取用户信息

wx.getUserProfile(Object object) | 微信开放文档

01 - 使用wx.getUserProfile

  1. <template>
  2. <div class='index-layout'>
  3. <div>index123</div>
  4. <button @click="getUserProfile"> 获取头像昵称 </button>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. name: 'index',
  10. mounted() {
  11. wx.login({
  12. success(res) {
  13. if (res.code) {
  14. //发起网络请求,把code传递给后端
  15. // wx.request({
  16. // url: 'https://example.com/onLogin',
  17. // data: {
  18. // code: res.code
  19. // }
  20. // })
  21. } else {
  22. console.log('登录失败!' + res.errMsg)
  23. }
  24. }
  25. })
  26. },
  27. methods: {
  28. getUserProfile(e) {
  29. // 推荐使用 wx.getUserProfile 获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认
  30. // 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
  31. wx.getUserProfile({
  32. desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
  33. // 点击允许
  34. success: (res) => {
  35. console.log('success',res);
  36. },
  37. // 点击拒绝
  38. fail: (err) => {
  39. console.log('fail',err);
  40. }
  41. })
  42. },
  43. }
  44. }
  45. </script>

注 : 现在已经不建议使用 wx.getUserProfile 或 wx.getUserInfo 

02 - 通过 wx.login 获取code wx.login(Object object) | 微信开放文档

  1. mounted() {
  2. wx.login({
  3. success(res) {
  4. if (res.code) {
  5. //发起网络请求,把code传递给后端
  6. wx.request({
  7. url: 'https://example.com/onLogin',
  8. data: {
  9. code: res.code
  10. }
  11. wx.setStorageSync('OPEN_ID', res.openId);
  12. wx.setStorageSync('UNION_ID', res.unionId);
  13. wx.getStorageSync('OPEN_ID')
  14. })
  15. } else {
  16. wx.showToast({
  17. title: '请求失败,请检查网络',
  18. icon: 'none'
  19. });
  20. // 设置顶部title
  21. wx.setNavigationBarTitle({
  22. title: '冲啊冲啊冲啊'
  23. });
  24. }
  25. }
  26. })
  27. },

03 - 获取用户手机号 获取手机号 | 微信开放文档

  1. <template>
  2. <button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
  3. 获取手机号
  4. </button>
  5. </template>
  6. <script>
  7. export default {
  8. name: 'index',
  9. methods: {
  10. getPhoneNumber(e) {
  11. // 如果点击了拒绝
  12. if (e.target.errMsg !== 'getPhoneNumber:ok'){
  13. return wx.showToast({
  14. title:'用户未同意授权手机号',
  15. icon:'none'
  16. })
  17. }
  18. // 如果点击确认
  19. cosnt { code, encryptedData, iv } = e.target
  20. // 把数据传给后端,后端会去解密拿到手机号的
  21. wx.request({
  22. url: 'https://example.com/onLogin',
  23. data: {
  24. appId: '',
  25. openId: '',
  26. code,
  27. encryptedData,
  28. iv
  29. },
  30. method: "post",
  31. success: function (res) {
  32. console.log(res);
  33. }
  34. })
  35. }
  36. }
  37. };
  38. </script>

2. 轮播图

代码

  1. <!-- HTML代码 -->
  2. <swiper class="nav"
  3. :circular="swiperOption.circular"
  4. :autoplay="swiperOption.autoplay"
  5. :interval="swiperOption.interval"
  6. :duration="swiperOption.duration"
  7. :display-multiple-items="swiperOption.displayItems">
  8. <swiper-item
  9. class="item"
  10. v-for="(item,index) in smallIconList"
  11. :key="index"
  12. catchtouchmove='catchTouchMove'>
  13. <img class="img" :src="item">
  14. </swiper-item>
  15. </swiper>
  16. <JS代码>
  17. <script>
  18. export default{
  19. data(){
  20. return{
  21. // 轮播图片
  22. smallIconList:[
  23. 'https://pic2.zhimg.com/v2-e6f99e63f4bcc0ae5d4d717553c5e511_r.jpg',
  24. 'https://n.sinaimg.cn/sinakd10116/760/w640h920/20200808/555d-ixkvvue2643771.jpg'
  25. ],
  26. // 轮播参数
  27. swiperOption: {
  28. autoplay: true, // 自动轮播
  29. circular: true, // 无缝连接轮博
  30. interval: 3000, // 多久切换一次
  31. duration: 1000, // 展示多久
  32. //displayItems: 3, // 同时展示多少个
  33. vertical: true, // 是否纵向
  34. }
  35. }
  36. },
  37. methods:{
  38. // 禁止用户滑动
  39. catchTouchMove(res){
  40. return false
  41. }
  42. }
  43. }
  44. </script>

3. 分享给好友

01 - html

  1. <button
  2. open-type="share"
  3. class="btn">
  4. 分享
  5. </button>

02 - js

  1. export default {
  2. components: {},
  3. data() {
  4. return {}
  5. },
  6. computed: {},
  7. onShow() {},
  8. // 转发参数
  9. // 注 : 和 methods 处在同一层次
  10. onShareAppMessage() {
  11. const params = {
  12. name: 'coder',
  13. age: 18
  14. }
  15. // 分享参数
  16. let str = ''
  17. for (const key in params) {
  18. str += `${key}=${params[key]}&`
  19. }
  20. str = str.substring(0, str.length - 1)
  21. return {
  22. title: '分享的title',
  23. path: '当前的页面路径 => pages/home/text/main?' + str
  24. }
  25. },
  26. methods: {}
  27. }

4. 获取当前页面路径及参数

  1. export default {
  2. components: {},
  3. data() {
  4. return {
  5. currentUrl: ''
  6. }
  7. },
  8. computed: {},
  9. // 和 mounted 差不多
  10. onShow() {
  11. this.currentUrl = this.getCurrentPageUrlWithArgs()
  12. },
  13. onShareAppMessage() { },
  14. methods: {
  15. // 获取当前页面url
  16. getCurrentPageUrlWithArgs() {
  17. const pages = getCurrentPages() // 获取加载的页面
  18. const currentPage = pages[pages.length - 1] // 获取当前页面的对象
  19. const url = currentPage.route // 当前页面url
  20. const options = currentPage.options // 如果要获取url中所带的参数可以查看options
  21. // 这里直接返回的话,返回的就是存路径
  22. // return url
  23. // 拼接url的参数
  24. let urlWithArgs = url + '?'
  25. for (let key in options) {
  26. urlWithArgs += `${key}=${options[key]}&`
  27. }
  28. urlWithArgs = urlWithArgs.substring(0, urlWithArgs.length - 1)
  29. return urlWithArgs
  30. },
  31. }
  32. }

5. 长按图片进行扫码

show-menu-by-longpress   =>   加上这个属性即可

  1. <image class="code-img"
  2. src="http://www.baidu.com"
  3. show-menu-by-longpress>
  4. </image>

四、mpvue开发中遇到的坑! 

1. 图片

01 - 不要在根元素上加背景图片

代码

  1. <!-- 提示 -->
  2. <!-- 在 main.js 中设置 Vue.prototype.$imageRootPath = '/static/images/' -->
  3. <template>
  4. <div class='topModule-layout' :style="{'background-image':'url('+bgimg+')'}">
  5. <img class="top-title-img" :src='topTitleImg' />
  6. </div>
  7. </template>
  8. <script>
  9. export default {
  10. name: 'topModule',
  11. data() {
  12. return {
  13. bgimg: this.$imageRootPath + 'fansWelfare/top-bgimg.png',
  14. topTitleImg: this.$imageRootPath + 'fansWelfare/top-title.png'
  15. };
  16. }
  17. };

结果 

02 - 线上背景图片不生效 

​​​​​​​代码

  1. <!-- 本地生效,线上不生效 -->
  2. <div @click="iconRun"
  3. class="buttom-bg"
  4. :class="{'no-buttom':showNotAllow}"
  5. :style="{'background-image':'url('+bgImg+')'}" />
  6. <!-- 使用img标签 -->
  7. <div @click="iconRun"
  8. class="buttom-bg"
  9. :class="{'no-buttom':showNotAllow}">
  10. <img :src="bgImg">
  11. </div>

2. swiper高度

01 - 直接设置css

  1. .swiper-info-layout{
  2. height: 748rpx;
  3. /*这个是swiper组件*/
  4. .swiper{
  5. height: 100%;
  6. margin: rem(15) rem(23) 0;
  7. }
  8. }

02 - 动态修改

html

  1. <template>
  2. <div class="swiper-info-layout">
  3. <swiper
  4. class="swiper"
  5. circular
  6. autoplay
  7. :interval="3000"
  8. :duration="500"
  9. :style="{height: swiperHeight }">
  10. <swiper-item
  11. v-for="(item, index) in swiperData"
  12. :key="index">
  13. <s-item :data-obj="item"></s-item>
  14. </swiper-item>
  15. </swiper>
  16. </div>
  17. </template>

js

  1. data() {
  2. return {
  3. swiperHeight: '0'
  4. }
  5. },
  6. mounted() {
  7. this.getEleHeight()
  8. },
  9. methods: {
  10. // 获取元素高度
  11. getEleHeight() {
  12. // 这里要延迟,不然获取不到
  13. setTimeout(() => {
  14. const query = wx.createSelectorQuery()
  15. // 通过类名获取元素,这里获取的是子组件的类名,方便设置
  16. query.select('.swiper-item-layout').boundingClientRect()
  17. query.exec((res) => {
  18. const winWid = wx.getSystemInfoSync().windowWidth // 获取当前屏幕的宽度
  19. const height = res[0].height // 获取组件高度
  20. const width = res[0].width // 获取组件宽度
  21. const swiperHeight = height / width * winWid + 'px' // 计算组件高度
  22. this.swiperHeight = swiperHeight // 设置组件高度
  23. })
  24. }, 100)
  25. }
  26. }

五、增加埋点 应用管理 - 帮助文档

1. 进入项目管理

2. 添加应用

3. 创建应用

4. SDK集成

微信小程序 - 帮助文档

5. 代码示例

main.js

  1. const gio = require('./utils/gio-minp/index.js').default
  2. // 每次发版需要修改version的值
  3. gio('init', '89d4e90ad33f3f2a', 'wx9107cfc9cb6414c5', {
  4. version: '1.0',
  5. vue: Vue
  6. })
  7. // 挂载全局gio
  8. Vue.prototype.$gio = gio

页面中监听

  1. <template>
  2. <div class="container"></div>
  3. </template>
  4. <script>
  5. export default {
  6. onShow() {
  7. // 埋点
  8. this.setGioPage()
  9. },
  10. onShareAppMessage() {
  11. return {
  12. title: this.title,
  13. path: `pages/xxx`
  14. }
  15. },
  16. methods: {
  17. setGioPage() {
  18. this.$gio('setPage', {
  19. pageName: `pages/account/subscribes/main?appointmentId=${this.appointmentId}`,
  20. title: this.title,
  21. source: 'xxx'
  22. })
  23. }
  24. }
  25. }
  26. </script>
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/782782
推荐阅读
相关标签
  

闽ICP备14008679号