一.准备工作

全局安装vue-cli

如果需要使用vue旧版本init功能,需安装桥接工具

1
npm install -g @vue/cli-init

随后创建一个基于mpvue-quickstart模板的新项目

1
vue init mpvue/mpvue-quickstart my-project

然后填写项目名、微信appid、项目描述、作者

切换到生成的项目根目录,使用下列命令进行安装

1
npm i

打包微信小程序,使用下列命令同步编译微信开发者工具

1
npm start

随后用微信小程序开发框架导入即可

注意开发时随时查阅小程序开发文档:https://developers.weixin.qq.com/miniprogram/dev/api/

引入ColorUI:下载好后,打开template,把colorui文件夹复制到小程序static文件夹下,并且在全局src->main.js导入包,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
import Vue from 'vue'
import App from './App'

import '../static/colorui/animation.wxss'
import '../static/colorui/main.wxss'
import '../static/colorui/icon.wxss'

Vue.config.productionTip = false
App.mpType = 'app'

const app = new Vue(App)
app.$mount()

开发时可查阅ColorUI文档:https://www.kancloud.cn/m22543/colorui/1289223

二.mpvue基础

简单的mpvue模板

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

</div>
</template>

<script>
export default{
data(){
return{}
}
}
</script>
<style>

</style>

data的return中可以像Vue那样定义数据,其大部分语法和Vue基本一致

生命周期

1
2
3
4
5
6
7
8
9
10
11
//生命周期,加在
onLoad(){
console.log('--onload--');
},
beforeMount(){
console.log('--onload--');
this.handleGetUserInfo();
},
mounted(){
console.log('--onload--');
}

非冒泡事件

1
2
3
<div @tap="toDetail" class="goStudy">
<p @tap.stop="handleChild">欢迎使用小程序</p>
</div>

新建页面及跳转

使用wx.navigatTo方法,对应url参考:/pages/list/main,注意以main结尾,list为pages下的文件夹,其中包含一个main.js,写法如下:

1
2
3
4
5
6
import Vue from 'vue'
import List from './list.vue'

const list = new Vue(List)

list.$mount()

还有一个list.vue文件参照上方template模板来写。

创建main.json来配置局部页面信息。

实测出现错误如下

VM704:1 未找到 app.json 中的定义的 pages “pages/list/main” 对应的 WXML 文件

解决方法:重新执行npm start

组件复用

同样要新建一个页面,main.js必须存在但是可以不写内容,将页面写好后即可进行引用:

1
2
3
4
5
6
7
 <script>
//进行组件注册
import ListTemp from'../list_template/list_template.vue' //包含组件页面
export default{
components: {ListTemp} //声明组件
}
</script>

随后在template中使用模板即可,注意要用<div></div>标签包围,示例:

1
2
3
4
<div>
<ListTemp></ListTemp> //相当于引入上方list_template.vue页面
<ListTemp></ListTemp>
</div>

Vuex

获取全局数据

安装

1
npm install vuex

全局加载,修改全局main.js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Vue from 'vue'
import store from './store/store' //新加入这行
import App from './App'

import '../static/colorui/animation.wxss'
import '../static/colorui/main.wxss'
import '../static/colorui/icon.wxss'

Vue.config.productionTip = false
App.mpType = 'app'

//将store对象放置在vue原型上,每个实例都可以使用
Vue.prototype.$store=store //新加入这行

const app = new Vue(App)

app.$mount()

中途遇到依赖问题,根据提示安装其他依赖即可

由于时间仓促,并没有仔细研究Vuex的工作原理,只了解大概使用方式

首先在pages下创建store文件夹,里面分别有以下文件

actions.js

getter.js

mutation-type.js

mutations.js

state.js

store.js

将模拟数据放在src->datas->list-data.js中

1)mutation-type.js

1
export const RECEIVE_LIST = 'receive_list'

2)action.js

1
2
3
4
5
6
7
8
9
10
import { RECEIVE_LIST } from "./mutation-type"
import listData from '../datas/list-data'

export default{
getList({commit}){
//触发对应mutations
console.log("actions")
commit(RECEIVE_LIST, listData)
}
}

3)mutations.js

1
2
3
4
5
6
7
8
import {RECEIVE_LIST} from './mutation-type'

export default{
[RECEIVE_LIST](state, {list_data}){
state.listTmp = list_data
console.log(state.listTmp)
}
}

4)state.js

1
2
3
export default{
listTmp: [] //列表数据,这个文件用来存储变量
}

5)store.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Vue from 'vue'
import Vuex from 'vuex'
import store from './store'
import state from './state'
import actions from './actions'
import mutations from './mutations'
import getters from './getter'

//声明使用Vuex
Vue.use(Vuex)

export default new Vuex.Store({
state,
actions,
getters,
mutations
})

目前暂时用到模拟数据,因此getter.js暂时不写

接下来加载动态数据,首先来到list.vue中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
import {mapState} from 'vuex'
import ListTemp from'../list_template/list_template.vue'
export default{
components: {ListTemp}, //组件注册
beforeMount(){
//分发action修改状态,填入action名字
this.$store.dispatch('getList')
},
//之前打成compunted,但程序没有任何报错,要特别注意
computed:{
//映射状态到组件,名字和state.js中一致
...mapState(['listTmp'])
}
}
</script>

接下来遍历数据,并传入至list_template.vue这个组件模板中(其他模板同理)

1
2
3
4
<div>
<ListTemp v-for="(item,index) in listTmp" :key="index" :item="item" :index="index"></ListTemp>
</div>
<!--使用:key="index"解除警告,item为listTmp中的一个对象数据,前面加:来传入模板-->

在list_template.vue中,可以使用Vue语法来获取数据,如,但是要注意声明传入参数:

1
2
3
4
5
6
7
<script>
export default{
props:[
'item','index'
]
}
</script>

这里注意使用v-bind:src来绑定图片,可以替换为 : 这个符号

1
<image :src="item.avatar" mode="widthFix"></image>

加载详情页数据

首先创建详情页detail,过程不再叙述

在list_template.vue中,绑定跳转事件并且要传入index索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
export default{
props:[
'item','index'
],
methods:{
toDetail(){
//跳转到详情页+传递参数index
wx.navigateTo({
url: '/pages/detail/main?index='+this.index,
success: (result) => {

},
fail: () => {},
complete: () => {}
});
}
}
}
</script>

在detail.vue中,获取索引及数据,由于之前已经分发过actions,跳转至此页无需再分发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
import {mapState} from 'vuex'
export default{
// onLoad(options){
// console.log(options)
// } 原生小程序写法
data(){
return {
detailObj:{}
}
},
beforeMount(){
//取代onload中options
this.index = this.$mp.query.index;
},
mounted(){
//更新state数据
this.detailObj = this.listTmp[this.index];
},
computed:{
...mapState(['listTmp'])
}
}
</script>

随后按照Vue的语法,在详情页载入数据即可

URL数据请求

注意,小程序中无法使用axios,会报XMLHttpRequest is not a constructor错误

安装flyio

1
npm install flyio

全局main.js引入flyio,注意要放在挂载应用前

1
2
3
var Fly=require("flyio/dist/npm/wx")
let fly = new Fly
Vue.prototype.$fly = fly

Get请求示例

1
2
3
4
5
6
7
8
9
const TEST_URL="http://47.95.32.217:8080/monitorApplication/maintenance/getAll?pageNum=0&pageSize=19";

this.$fly.get(TEST_URL)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});

获取用户code

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
wx.login({
success: function (res) {
console.log(res) //res.code
if (res.code) {
console.log('通过login接口的code换取openid');
wx.request({
url: 'https://api.weixin.qq.com/sns/jscode2session',
data: {
//填上自己的小程序唯一标识
appid: '',
//填上自己的小程序的 app secret
secret: '',
grant_type: 'authorization_code',
js_code: res.code
},
method: 'GET',
header: { 'content-type': 'application/json'},
success: function(openIdRes){
console.info("登录成功返回的openId:" + openIdRes.data.openid);
},
fail: function(error) {
console.info("获取用户openId失败");
console.info(error);
}
})
}
}
})

三.小程序案例

使用Promise.all上传多张图片

在项目开发中,会遇到上传图片未完成就提交了商品信息的情况,这样提交的图片URL为undefined,这是由于wx.uploadFile为异步执行造成的,因此要使用promise来保证其先执行完,再进行其他操作

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
var tempFilePaths = this.imgList;
var submitImgList = this.submitImgList;

var promise = Promise.all(tempFilePaths.map((tempFilePath, index) => {
var that = this;
return new Promise(function (resolve, reject) {
wx.uploadFile({
url: that.globalData.backgroundURL + 'upload/productImage',
filePath: tempFilePath,
name: 'productImage',
formData: {
},
success: function (res) {
resolve(res.data);
var data = JSON.parse(res.data);
//设置图片链接
that.submitImgList.push(that.globalData.backgroundURL + data.data);
that.resultCode = 200.
},
fail: function (err) {
reject(new Error('failed to upload file'));
}
});
});
}));

var that = this;
promise.then(function (results) {
console.log(results);
that.submitProduct();
}).catch(function (err) {
console.log(err);
});