微信小程序起步(2)

安装

官方文档
首先下载微信小程序的开发者工具小程序开发者工具,再下载微信小程序DEMO源码
qq20161016-1
安装开发者工具,并解压DEMO源码,在开发者工具中导入源码项目

注册

打开微信公众平台,在里面注册账号选择小程序,用户体选择个人

app.json(全局配置)

我们使用app.json文件来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多tab等

image

pages

如果学过其他框架,可以把它理解为路由,在app.json文件的pages属性里面定义路由和对应的组件,默认是在pages文件夹里面寻找xxx组件的xxx.js文件,当然没有后缀

pages/index/index => page文件夹下的index组件的文件夹下的所有资源

pages接受一个数组,每一项都是字符串,来指定小程序由哪些页面组成,每一项代表对应页面的路径+文件名信息

  • 数组的第一项代表小程序的初始页面,小程序中新增/减少页面,都需要对 pages 数组进行修改
  • 文件名不需要写文件后缀,因为框架会自动去寻找路径.json,.js,.wxml,.wxss的四个文件进行整合
1
2
3
4
5
6
7
8
9
{
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/test/test",
"pages/text/text"
],
//code
}

tabBar

tabBar其实就是配置底部的选项卡,在app.json文件的tabBar属性里面定义底部的选项卡的详细配置

image

如果我们的小程序是一个多 tab 应用(客户端窗口的底部或顶部有tab栏可以切换页面),那么我们可以通过tabBar配置项指定tab栏的表现,以及tab切换时显示的对应页面

通过页面跳转wx.navigateTo或者页面重定向wx.redirectTo所到达的页面,即使它是定义在 tabBar 配置中的页面,也不会显示底部的tab栏

tabBar是一个数组,只能配置最少2个、最多5个tab,tab按数组的顺序排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
//code
"tabBar": {
"color": "#666",
"selectedColor": "#268dcd",
"borderStyle": "white",
"backgroundColor": "#fafafa",
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "image/wscats.png",
"selectedIconPath": "image/wscats.png",
"text": "首页"
},
{
"pagePath": "pages/logs/logs",
"text": "分类"
}
//code
]
}
}

一般我们可以新建一个放图标的文件夹image,此文件夹跟pages同级,然后在里面我们可以放图标

image

我在文件夹里面放了两张图片wscats.png和wscats-active.png,我们就可以在iconPath和selectedIconPath里面把图片引进来,设置的分别是切换选项卡时候出现的图标

tabBar属性 作用
color 未选中时候文字颜色
selectedColor 选中时候文字颜色
borderStyle 边样式,可以设置颜色和粗细
backgroundColor 背景颜色
list 详情看下表

list接受一个数组,数组中的每个项都是一个对象,其属性值如下
image

list属性 作用
pagePath 跳转路由
iconPath 未选中时候的图标
selectedIconPath 选中时候的图标
text 文字描述

window

用于设置小程序的状态栏、导航条、标题、窗口背景色
image

image

networkTimeout

可以设置各种网络请求的超时时间

image

debug

可以在开发者工具中开启debug模式,在开发者工具的控制台面板,调试信息以info的形式给出,其信息有Page的注册,页面路由,数据更新,事件触发 。可以帮助开发者快速定位一些常见的问题

page.json

每一个小程序页面也可以使用.json文件来对本页面的窗口表现进行配置。 页面的配置比app.json全局配置简单得多,只是设置app.json中的window配置项的内容,页面中配置项会覆盖app.json的window中相同的配置项

页面的.json只能设置window相关的配置项,以决定本页面的窗口表现,所以无需写 window 这个键

如图,在logs组件里面的logs.json设置对应的参数,那就会覆盖app.json原有的配置项
image

xxx.json(页面配置)

每一个小程序页面也可以使用.json文件来对本页面的窗口表现进行配置

页面的配置只能设置app.json中部分window配置项的内容,页面中配置项会覆盖app.jsonwindow中相同的配置项,示例如下

1
2
3
4
5
6
7
{
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationBarTitleText": "微信接口功能演示",
"backgroundColor": "#eeeeee",
"backgroundTextStyle": "light"
}

组件

可以建立一个components的目录

2018-10-24 10 02 29

tab-content1.wxml写入以下代码,这里可以配合使用<slot></slot>让我们使用组件的时候插入片段

1
2
3
4
5
<view>
<!--components/tab-content1/tab-content1.wxml-->
<text>components/tab-content1/tab-content1.wxml</text>
<slot></slot>
</view>

里面新建一个目录为tab-content1的目录作为组件的放置位置,然后可以在pages目录下的index.json下写入以下代码

1
2
3
4
5
{
"usingComponents": {
"tab-content1": "/components/tab-content1/tab-content1"
}
}

然后在pages目录下的index.wxml下写入以下代码,来使用组件

1
2
3
4
5
<view class="weui-tab__content" hidden="{{activeIndex != 0}}">
<tab-content1>
<view>这里是插入到组件slot中的内容</view>
</tab-content1>
</view>

生命周期

组件里面有的生命周期,可以在这里做逻辑或者监听其他组件的逻辑来通信数据

定义段 类型 是否必填 描述
created Function 组件生命周期函数,在组件实例进入页面节点树时执行,注意此时不能调用 setData
attached Function 组件生命周期函数,在组件实例进入页面节点树时执行
ready Function 组件生命周期函数,在组件布局完成后执行,此时可以获取节点信息(使用 SelectorQuery
moved Function 组件生命周期函数,在组件实例被移动到节点树另一个位置时执行
detached Function 组件生命周期函数,在组件实例被从页面节点树移除时执行

组件通信

组件和组件之间的通信,我个人会用$on$emit来实现,参考发布订阅模式

父传子的数据通信

父组件在子组件的标签值上传递值

1
<pannel channel="hot"></pannel>

子组件<pannel>properties属性接受,逻辑中用this.properties.channel获取值,这种方法类似于vue和react中的props方法

1
2
3
4
5
6
7
8
Component({
/**
* 组件的属性列表
*/
properties: {
channel: String
}
}

模板语法

使用 name 属性,作为模板的名字。然后在<template/>内定义代码片段,可以构建一个可复用的模板

1
2
3
<template name="msgItem">
<view> <text> {{index}}: {{msg}} </text> <text> Time: {{time}} </text> </view>
</template>

使用模板,先 import 对应模板的文件路径,使用 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入

1
2
3
4
5
6
7
8
9
10
11
12
<import src="item.wxml" />
<template is="msgItem" data="{{text: 'forbar'}}" />
<template is="msgItem" data="{{...item}}" />
Page({
data: {
item: {
index: 0,
msg: 'this is a template',
time: '2016-09-15'
}
}
})

is 属性可以使用 Mustache 语法,来动态决定具体需要渲染哪个模板:

1
2
3
4
5
6
7
8
9
10
<template name="odd">
<view> odd </view>
</template>
<template name="even">
<view> even </view>
</template>

<block wx:for="{{[1, 2, 3, 4, 5]}}">
<template is="{{item % 2 == 0 ? 'even' : 'odd'}}" />
</block>

WeUI

在Github下载WeUI for 小程序 为微信小程序量身设计 Github仓库

weui-wxss/dist/style/目录中的weui.wxss放到程序根目录下,然后在app.wxss全局引用weui样式

1
@import 'weui.wxss';

image

然后就可以复制粘贴src/example文件夹里面的组件进行开发了

导航

导航相当于路由跳转,用navigator标签,然后在属性值上面放自己定义好的组件页面

1
2
3
4
5
6
7
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/test/test",
"pages/text/text",
"pages/detail/detail"
],

比如要跳到详情页组件就写url="/pages/detail/detail",如果要跳到主页那就写url="/pages/index/index",根据pages属性值里面定义好的路由去改相应的链接地址

1
<navigator url="/pages/detail/detail" class="weui-media-box weui-media-box_appmsg" hover-class="weui-cell_active"></navigator>

路由传参

我们在链接上带上哈希值,然后传递给详情页

1
<navigator url="/pages/detail/detail?id={{index}}" class="weui-media-box weui-media-box_appmsg" hover-class="weui-cell_active">

在详情页中获取options中的哈希值

1
2
3
4
5
Page({
onLoad: function (options) {
console.log(options)
}
})

获取视图输入值

input输入框显示自己输入的值,bindinput来对输入的值进行接受,再把值赋给一个变量

1
<input name="user" value="{{user}}" bindinput="inputUser" type="text" />
1
`value="{{user}}"`显示绑定的值,bindinput绑定事件,在e中的detail属性中获取
1
2
3
4
5
6
inputUser: function (e) {
console.log(e.detail.value)
this.setData({
user: e.detail.value
})
}

常用API

wx.request(Object object)
发起HTTPS网络请求,这个相当于微信小程序给我们封装好的ajax请求

在使用之前记得要去后台页面设置安全域名
2018-10-24 1 03 49

1
2
3
4
5
6
7
8
9
10
11
12
13
wx.request({
url: 'test.php', //仅为示例,并非真实的接口地址
data: {
x: '',
y: ''
},
header: {
'content-type': 'application/json' // 默认值
},
success (res) {
console.log(res.data)
}
})

2018-10-24 1 05 44

当然如果只是测试可以勾选不校验合法域名

mpvue

mpvue github地址 请参见是一个使用Vue.js开发小程序的前端框架。框架基于Vue.js核心,mpvue修改了Vue.js的runtimecompiler实现,使其可以运行在小程序环境中,从而为小程序开发引入了整套Vue.js开发体验

安装

搭建环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 1. 先检查下 Node.js 是否安装成功
$ node -v
v8.9.0

$ npm -v
5.6.0

# 2. 可以考虑切换源为 taobao 源
$ npm set registry https://registry.npm.taobao.org/

# 3. 全局安装 vue-cli
# 一般是要 sudo 权限的
$ npm install --global vue-cli@2.9

# 4. 创建一个基于 mpvue-quickstart 模板的新项目
# 新手一路回车选择默认就可以了
$ vue init mpvue/mpvue-quickstart my-project

# 5. 安装依赖
$ cd my-project
$ npm install
$ npm run dev

注意事项

新增的页面需要重新npm run dev来进行编译,比如新建的vue组件需要重新编译,小程序的工具才能看出效果

对应小程序的文件

vue文件对应小程序里面的那些文件

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
/* 这部分相当于原生小程序的 app.wxml */
</template>
<script>
/* 这部分相当于原生小程序的 app.js */
export default {
created () {
}
}
</script>
<style>
/* 这部分相当于原生小程序的 app.wxss */
</style>

全局的app.json就是对应小程序的app.json

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
{
"pages": [
"pages/index/main",
"pages/logs/main",
"pages/counter/main",
"pages/setting/main"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "你是谁",
"navigationBarTextStyle": "black"
},
"tabBar": {
"list": [{
"pagePath": "pages/index/main",
"text": "首页"
}, {
"pagePath": "pages/logs/main",
"text": "日志"
},{
"pagePath": "pages/counter/main",
"text": "vuex"
}, {
"pagePath": "pages/setting/main",
"text": "设置"
}]
}
}

局部的main.json对应的是page里面的xxx.json

1
2
3
4
{
"navigationBarTitleText": "查看启动日志",
"navigationBarBackgroundColor": "#58bc58"
}

Vuex

状态管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 = stat
obj.count -= 1
}
}
})
export default store

组件可以通过store.commit('increment'),注意发现在语法上用单引号,结尾不要用分号,还有函数括号前要放空格,不然会报错

1
2
3
4
5
6
7
8
import store from '../store'
export default {
methods: {
edit () {
store.commit('increment')
}
}
}

可以直接使用store.state.xxx获取state的值

1
2
3
4
5
6
7
8
import store from '../store'
export default {
computed: {
count () {
return store.state.count
}
}
}

其他注意点

    1. 在模板中,动态插入HTML的v-html指令不可用

小程序的界面并不是基于浏览器的BOM/DOM的,所以不能动态的在界面模板里直接插入HTML片段来显示

如果要插入html片段可以用<rich-text>组件或者wxParse(https://github.com/icindy/wxParse)来实现%E6%9D%A5%E5%AE%9E%E7%8E%B0)

    1. 在模板中,用于数据绑定的双括号语法中的表达式功能存在诸多限制,以下功能都不能使用

表达式中放函数

1
<div>{{ formatMessage(msg) }}</div>

调用对象的方法

1
<div>{{ msg.trim().split(',').join('#') }}</div>

过滤器

1
<div>{{ msg | format }}</div>
    1. 在模板中,除事件监听外,其余地方都不能调用methods下的函数
1
<div v-if="getErrorNum() > 0  && code == 10001" class="error">{{ errorMsg }}</div>
    1. 在模板中,不支持直接绑定一个对象到style或class属性上

官方建议的方案如下

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
<template>
<div :class="classStr"></div>
</template>
<script>
export default {
data() {
return {
classObject: {
active: true,
'text-danger': false
}
}
},
computed: {
classStr() {
let arr = []
for (let p in this.classObject) {
if (this.classObject[p]) {
arr.push(p)
}
}
return arr.join(' ')
}
}
}
</script>
    1. 在模板中,嵌套使用v-for时,必须指定索引index
1
2
3
<ul v-for="(category, index) in categories">
<li v-for="(product, productIndex) in category.products">{{product.name}}</li>
</ul>
  • 事件处理中的注意点

在mpvue中,一般可以使用Web的DOM事件名来绑定事件,mpvue会将Web事件名映射成对应的小程序事件名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 左侧为WEB事件 : 右侧为对应的小程序事件
{
click: 'tap',
touchstart: 'touchstart',
touchmove: 'touchmove',
touchcancel: 'touchcancel',
touchend: 'touchend',
tap: 'tap',
longtap: 'longtap',
input: 'input',
change: 'change',
submit: 'submit',
blur: 'blur',
focus: 'focus',
reset: 'reset',
confirm: 'confirm',
columnchange: 'columnchange',
linechange: 'linechange',
error: 'error',
scrolltoupper: 'scrolltoupper',
scrolltolower: 'scrolltolower',
scroll: 'scroll'
}
    1. 对于表单,请直接使用小程序原生的表单组件

一句话,表单组件又多又复杂,框架可能Hold不住。所以在实际开发中,推荐直接使用小程序的表单组件标签来写,而不是使用Web的表单组件标签来写。当然了,在mpvue中使用了小程序的组件标签,数据绑定功能还是完全可以用的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div>
<picker @change="handlePickerChange" :value="selectedIndex" :range="messages">
<view class="picker">当前消息:{{ messages[selectedIndex] }}</view>
</picker>
</div>
</template>

<script>
export default {
data () {
return {
selectedIndex: 0,
messages: ['Hello', 'World', 'Haha']
}
},
methods: {
handlePickerChange (e) {
console.log(e)
}
}
}
</script>
  • vue-router和axios无法使用

另外,在Vue开发Web应用的时候,通常使用vue-router来进行页面路由。但是在mpvue小程序开发中,不能用这种方式,请使用标签和小程序原生API wx.navigateTo等来做路由功能

还有就是请求后端数据,我们通常在Web开发中使用axios等ajax库来实现,但是在小程序开发中也是不能用的,也请使用小程序的原生API wx.request等来进行

参考文档