微信小程序介绍

微信小程序出来也有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 支持