微信小程序介绍
微信小程序出来也有2年多了,对于微信小程序就不做过多介绍。
开发准备
根据指引填写信息和提交相应的资料,就可以拥有自己的小程序帐号。
- 下载微信开发者工具
进入下载页面,根据系统下载对应版本,安装后就可以开始开发了。
目录结构
一个最简单的微信小程序目录结构如下:
Mpvue 介绍
mpvue 是使用 Vue 开发小程序的前端框架,主要是修改了vue 的runtime和compiler,以便支持小程序环境。起初只支持微信小程序,从2.0版本开始支持百度、头条和支付宝小程序。下面介绍的主要还是以微信小程序为主。
快速上手
mpvue 构建工具是基于vue-cli 2.x 版本开发的,只能通过vue-cli 2.9 版本初始化新项目。
$ npm install --global vue-cli@2.9
# 创建一个基于 mpvue-quickstart 模板的新项目
$ vue init mpvue/mpvue-quickstart mpvue-demo
# 安装依赖
$ cd mpvue
$ npm install 或者 yarn
# 开发
$ npm run dev
# 构建
$ npm run build
# 指定平台的开发时构建(微信、百度、头条、支付宝)
> npm run dev:wx
> npm run dev:swan
> npm run dev:tt
> npm run dev:my
# 指定平台的打包构建
> npm run build:wx
> npm run build:swan
> npm run build:tt
> npm run build:my
安装依赖,运行npm run dev ,使用微信开发者工具打开工程目录文件。
在上图中可以看到控制台有个VM1502:1 无效的 appJSON["tabBar"]["items"] 提示。
tabBar 是用来配置底部菜单栏的,mpvue 默认生成是的基于2.0版本,支持多种小程序开发,微信小程序、百度小程序、头条小程序的tabBar 都是使用list 定义各子项,而支付宝小程序使用items 来定义,所以这里定义了两种配置方式。
编译成功后就可以愉快的修改代码进行开发啦。
和原生语法使用上的差异
数据绑定
原生小程序使用方式为:
value="{{value}}"
mpvue 使用方式:
v-bind:value="value"
//或者
:value="value"
事件绑定
微信小程序原生事件是通过bind 绑定的,如bindtap bindchange ,在mpvue中,需要改成@ 形式,如@click @change 。
获取参数
page 中获取页面跳转传递的参数,可以在 onLoad 事件中使用this.$root.$mp.query 获取。
// pageA
wx.navigateTo({
url: 'pages/pageB/main?id=xxx'
})
// pageB
onLoad() {
const { id } = this.$root.$mp.query
}
在原生语法中,获取表单等组件的值,使用的是e.detail.value ,在mpvue 中,需使用e.mp.detail.value 获取。
<input @input="onInput"></input>
// ...
onInput(e) {
console.log(e.mp.detail.value)
}
开发
为了提高开发效率和可复用性,一般会使用Less或Sass开发css。
支持Less
安装依赖:
npm i less less-loader -D
支持Scss
npm i node-sass sass-loader -D
全局CSS
定义在App.vue 中的style,会被编译成app.wxss ,就是全局样式,每个页面都可以直接使用里面定义的 class。
支持全局Scss/Less 定义的vars 和mixins
如果我们有一个定义全局变量和mixins 的文件index.less :
@blue: #409EFF;
.multi-line(@a) {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: @a;
overflow: hidden;
}
现在想在其它页面中引用全局变量,需要手动 import。
<style scoped lang="less">
@import '../src/style/index.less';
.article{
color: @blue;
.multi-line(2);
}
</style>
问题来了,在多个页面中都需要引用全局变量和mixins,需要在每个页面上手动引用,一旦更改这个文件的路径,需要逐个进行修改。有没有其他方法,引用一次所有页面都能使用呢?答案是肯定的。
我们可以借助 sass-resources-loader 插件来实现,它可以在编译时将全局的变量和mixins 注入到每个页面中,不需要在页面中逐个导入。别被这个插件的文件名迷惑,它除了支持 sass,还支持 less、postcss等。
首先安装依赖:
npm install sass-resources-loader --save-dev
然后定位到 build/utils.js 文件中的如下代码:
return {
css: generateLoaders(),
wxss: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
修改成如下代码即可:
return {
css: generateLoaders(),
wxss: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less').concat(
{
loader: 'sass-resources-loader',
options: {
resources: path.resolve(__dirname, '../src/style/index.less'),
}
}
),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
上述修改,也同样适用于 scss:
return {
css: generateLoaders(),
wxss: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass').concat(
{
loader: 'sass-resources-loader',
options: {
resources: path.resolve(__dirname, '../src/style/index.less'),
}
}
),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
使用vuex
mpvue 也是支持 vuex 的,使用方式和在h5上几乎一致。
定义store:
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment: (state) => {
const obj = state
obj.count += 1
},
decrement: (state) => {
const obj = state
obj.count -= 1
}
}
})
export default store
使用:
import store from './store'
export default {
computed: {
count () {
return store.state.count
}
},
methods: {
increment () {
store.commit('increment')
},
decrement () {
store.commit('decrement')
}
}
}
使用vant
为了快速上手和UI的美化,就有了使用第三方UI库的需求,目前流行的小程序UI库有 vant-weapp、iview-weapp、wux-weapp等,这些都是基于components 开发的,mpvue同样是支持原生框架的自定义组件的。这里以vant-weapp 为例讲解如何在mpvue中使用自定义组件。
vant-weapp 是有赞出的vant的小程序版本,在使用之前,最好能对 微信小程序自定义组件 有一定的了解。
获取vant 源码
使用npm 安装
npm i vant-weapp
或者直接通过git 下载 vant 源代码
git clone https://github.com/youzan/vant-weapp.git
然后将下载下来的整个dist 目录复制到 mpvue工程下的static 下(一定要是static目录,不然mpvue会编译处理出现错误),然后给dist改名为 vant。
dist目录是ES6版本,需要在项目配置中开启 ES6转ES5 功能,如果不想开启,可以使用 lib 目录(对应ES5)
使用vant
为需要使用自定义组件的页面进行配置,在对应的页面 如src/pages/index/main.json (没有该文件,则新建一个)中进行如下配置:
{
"usingComponents": {
"van-button": "../../static/vant/button/index"
}
}
然后在index.vue 中使用:
<van-button type="primary">按钮</van-button>
上面的使用方式适用于大部分组件。
对于 Toast、Dialog、Notify等组件,还需要手动处理。
同样,也需要引入需要的组件:
{
"usingComponents": {
"van-dialog": "../../static/vant/dialog/index",
"van-notify": "../../static/vant/notify/index",
"van-toast": "../../static/vant/toast/index"
}
}
然后在页面中引入对应的js文件,并且在template 中挂载一个节点。
<template>
<div>
<van-dialog id="van-dialog" />
<van-notify id="van-notify" />
<van-toast id="van-toast" />
</div>
</template>
<script>
import Dialog from '../../../static/vant/dialog/dialog'
import Toast from '../../../static/vant/toast/toast'
import Notify from '../../../static/vant/notify/notify'
// ...
Toast('测试Toast')
Notify('Notify 测试')
Dialog.alert({
message: '弹窗内容'
}).then(() => {
// on close
});
</script>
对于不需要使用的组件,可以删除以减小小程序体积。
2019.7.29更新:
在2019年7月27日,iView 2019 新品发布会上,发布了 iview-mpvue 版本,这个是首个针对mpvue 发布的UI库,是iview 与 mpvue 合作推出的。
iview-mpvue 的使用方式和普通的vue组件没什么区别:
<template>
<i-button type="primary" @click="handleClick">这是一个按钮</i-button>
</template>
<script>
import button from '../../dist/components/button/button'
export default {
components: {
'i-button': button
}
}
</script>
与上面提到的,使用 usingComponents 不同的是,它不仅能够支持微信小程序,还能支持百度、支付宝、头条小程序。
踩坑
同一页面被多次打开引起的问题
从列表页 -> a详情页 -> 返回 列表页 -> b详情页,详情页被打开多次,每次打开的是不同id的详情,如果不做处理,会先展示a 的信息,然后再展示 b的信息。
mpvue在处理的时候,数据公用了一个对象,也没有去解决这种“诡异”的设计。
对于这个问题,我们可以在每次进入页面的时候,重置一下数据:
data() {
return {
name: ''
}
},
onLoad() {
this.name = ''
}
网上还有其他的解决方法。
Mpvue不足
- 所有的组件都是编译成 template,而不是component
- 新加的页面和组件需要重新npm run dev 才能生效
- 不支持在 template 中使用函数和过滤器(受限于wxml的数据绑定),Megalo 支持