微信小程序学习笔记

微信小程序

欢迎访问我的博客,祝码农同胞们早日走上人生巅峰,迎娶白富美~~~

微信小程序,简称小程序,英文名Mini Program,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用。

关于此学习的测试项目都暂时保存在https://github.com/ForeManWang/wxapp-study

微信小程序账号与工具

在线文档:https://mp.weixin.qq.com/debug/wxadoc/dev/

小程序开发者账号注册

微信公众平台:https://mp.weixin.qq.com/

小程序开发者账号注册:https://mp.weixin.qq.com/wxopen/waregister?action=step1

微信开发者工具

微信开发者工具:https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html

小程序在线Demo

微信小程序文件结构

主体文件结构

主体部分由三个文件组成,必须放在项目的根目录,如下:

文件 必填 作用
app.js 小程序逻辑
app.json 配置文件——小程序公共设置,主要界面外观设置
app.wxss 小程序公共样式表

页面文件结构

通过开发者工具快速创建了一个 QuickStart 项目。可以留意到这个项目里边生成了不同类型的文件:

  1. .json 后缀的 JSON 配置文件
  2. .wxml 后缀的 WXML(Wei Xin Markup Language) 模板文件
  3. .wxss 后缀的 WXSS(Wei Xin Style Sheets) 样式文件
  4. .js 后缀的 JS 脚本逻辑文件

接下来我们分别看看这4种文件的作用。

页面由四个文件组成,分别是:

文件类型 必填 作用
js 页面逻辑 ( 微信小程序没有window和document对象 )
wxml 页面结构 ( XML语法,不是HTML语法 )
wxss 页面样式表 ( 拓展了rpx尺寸单位,微信专属响应式像素 )
json 页面配置 ( 不能写注释,否则编译报错 )

微信小程序全局配置

app.json 配置项列表

app.json 是当前小程序的全局配置,包括了小程序的所有页面路径、界面表现、网络超时时间、底部 tab 等。可以看到生成的app.json配置内容如下:

1
2
3
4
5
6
7
8
9
{
"pages": ["pages/index/index", "pages/logs/logs"],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "black"
}
}

app.json配置各项的含义

属性 类型 必填 描述 最低版本
pages String Array 描述当前小程序所有页面路径,通常文件名和页面各文件名都相同
window Object 定义小程序所有页面的顶部背景颜色,文字颜色定义等。
tabBar Object 底部 tab 栏的表现
networkTimeout Object 网络超时时间
debug Boolean 是否开启 debug 模式,默认关闭
functionalPages Boolean 是否启用插件功能页,默认关闭 2.1.0
subpackages Object Array 分包结构配置 1.7.3
workers String Worker 代码放置的目录 1.9.90
requiredBackgroundModes String Array 需要在后台使用的能力,如「音乐播放」
plugins Object 使用到的插件 1.9.6
preloadRule Object 分包预下载规则 2.3.0
resizable Boolean iPad 小程序是否支持屏幕旋转,默认关闭 2.3.0
navigateToMiniProgramAppIdList String Array 需要跳转的小程序列表,详见 wx.navigateToMiniProgram 2.4.0
usingComponents Object 全局自定义组件配置 开发者工具 1.02.1810190
permission Object 小程序接口权限相关设置 微信客户端 7.0.0

pages

用于指定小程序由哪些页面组成,每一项都对应一个页面的 路径+文件名 信息。文件名不需要写文件后缀,框架会自动去寻找对于位置的 .json, .js, .wxml, .wxss 四个文件进行处理。

例如app.json中,此时数组中第一项为默认首页,即index是首页

1
2
3
{
"pages": ["pages/index/index", "pages/logs/logs"]
}

window

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

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

属性 类型 默认值 描述 最低版本
navigationBarBackgroundColor HexColor #000000 导航栏背景颜色,如 #000000
navigationBarTextStyle String white 导航栏标题颜色,仅支持 black / white
navigationBarTitleText String 导航栏标题文字内容
navigationStyle String default 导航栏样式,仅支持以下值: default 默认样式 custom 自定义导航栏,只保留右上角胶囊按钮。参见注2。 微信客户端 6.6.0
backgroundColor HexColor #ffffff 窗口的背景色
backgroundTextStyle String dark 下拉 loading 的样式,仅支持 dark / light
backgroundColorTop String #ffffff 顶部窗口的背景色,仅 iOS 支持 微信客户端 6.5.16
backgroundColorBottom String #ffffff 底部窗口的背景色,仅 iOS 支持 微信客户端 6.5.16
enablePullDownRefresh Boolean false 是否开启当前页面的下拉刷新。 详见 Page.onPullDownRefresh
onReachBottomDistance Number 50 页面上拉触底事件触发时距页面底部距离,单位为px。 详见 Page.onReachBottom
pageOrientation String portrait 屏幕旋转设置,仅支持 auto / portrait 详见 响应显示区域变化 微信客户端 6.7.3
  • 注1:HexColor(十六进制颜色值),如”#ff00ff”
  • 注2:关于navigationStyle
  • 客户端 7.0.0 以下版本,navigationStyle 只在 app.json 中生效。
  • 客户端 6.7.2 版本开始,navigationStyle: custom 组件无效
  • 开启 custom 后,低版本客户端需要做好兼容。开发者工具基础库版本切到 1.7.0(不代表最低版本,只供调试用)可方便切到旧视觉

如 app.json :

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

微信接口功能演示

tabBar

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

属性 类型 必填 默认值 描述 最低版本
color HexColor tab 上的文字默认颜色,仅支持十六进制颜色
selectedColor HexColor tab 上的文字选中时的颜色,仅支持十六进制颜色
backgroundColor HexColor tab 的背景色,仅支持十六进制颜色
borderStyle String black tabbar上边框的颜色, 仅支持 black / white
list Array tab 的列表,详见 list 属性说明,最少2个、最多5个 tab
position String bottom tabBar的位置,仅支持 bottom / top
custom Boolean false 自定义 tabBar,见详情 2.5.0
  1. tabBar 中的 list 是一个数组,只能配置最少2个、最多5个 tab,tab 按数组的顺序排序。

属性说明

属性 类型 必填 说明
pagePath String 页面路径,必须在 pages 中先定义
text String tab 上按钮文字
iconPath String 图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px,当 postion 为 top 时,此参数无效
selectedIconPath String 选中时的图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px ,当 postion 为 top 时,此参数无效

示例

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
{
"pages":[
"pages/index/index",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle":"black",
},
"debug": true,
"tabBar": {
"color": "#444",
"backgroundColor": "#e0e0e0",
"SelectedColor": "#219be3",
"boderStyle": "black",
"position": "bottom",
"list": [
{
"text": "Home",
"PagePath": "pages/index/index",
"iconPath": "icons/grid-01.png"
},
{
"text": "logs",
"PagePath": "pages/logs/logs",
"iconPath": "icons/grid-02.png"
}
]
}
}

图示:

networkTimeout

各类网络请求的超时时间,单位均为毫秒。

属性 类型 必填 默认值 说明
request Number 60000 wx.request 的超时时间,单位:毫秒。
connectSocket Number 60000 wx.connectSocket 的超时时间,单位:毫秒。
uploadFile Number 60000 wx.uploadFile 的超时时间,单位:毫秒。
downloadFile Number 60000 wx.downloadFile 的超时时间,单位:毫秒。

debug

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

functionalPages

基础库 2.1.0 开始支持,低版本需做兼容处理。

启用插件功能页时,插件所有者小程序需要设置其 functionalPagestrue

subpackages

微信客户端 6.6.0 ,基础库 1.7.3 及以上版本支持。

启用分包加载时,声明项目分包结构。

写成 subPackages 也支持。

workers

基础库 1.9.90 开始支持,低版本需做兼容处理。

使用 Worker 处理多线程任务时,设置 Worker 代码放置的目录。

requiredBackgroundModes

微信客户端 6.7.2 及以上版本支持。

申明需要后台运行的能力,类型为数组。目前支持以下项目:

  • audio: 后台音乐播放

如:

1
2
3
4
{
"pages": ["pages/index/index"],
"requiredBackgroundModes": ["audio"]
}

注:在此处申明了后台运行的接口,开发版和体验版上可以直接生效,正式版还需通过审核。

plugins

基础库 1.9.6 开始支持,低版本需做兼容处理。

声明小程序需要使用的插件。

preloadRule

基础库 2.3.0 开始支持,低版本需做兼容处理。

声明分包预下载的规则。

resizable

基础库 2.3.0 开始支持,低版本需做兼容处理。

在 iPad 上运行的小程序可以设置支持屏幕旋转。

基础库 2.4.0 开始支持,低版本需做兼容处理。

当小程序需要使用 wx.navigateToMiniProgram 接口跳转到其他小程序时,需要先在配置文件中声明需要跳转的小程序 appId 列表,最多允许填写 10 个。

usingComponents

开发者工具 1.02.1810190 及以上版本支持。

在此处声明的自定义组件视为全局自定义组件,在小程序内的页面或自定义组件中可以直接使用而无需再声明。

permission

微信客户端 7.0.0 及以上版本支持

小程序接口权限相关设置。字段类型为 Object,结构为:

属性 类型 必填 默认值 描述
scope.userLocation PermissionObject 位置相关权限声明

PermissionObject 结构

属性 类型 必填 默认值 说明
desc string 小程序获取权限时展示的接口用途说明。最长30个字符

如:

1
2
3
4
5
6
7
8
{
"pages": ["pages/index/index"],
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
}
}

微信小程序页面配置

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

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

配置示例

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

页面配置项列表

属性 类型 默认值 描述 最低版本
navigationBarBackgroundColor HexColor #000000 导航栏背景颜色,如 #000000
navigationBarTextStyle String white 导航栏标题颜色,仅支持 black / white
navigationBarTitleText String 导航栏标题文字内容
navigationStyle String default 导航栏样式,仅支持以下值: default 默认样式 custom 自定义导航栏,只保留右上角胶囊按钮 微信客户端 7.0.0
backgroundColor HexColor #ffffff 窗口的背景色
backgroundTextStyle String dark 下拉 loading 的样式,仅支持 dark / light
enablePullDownRefresh Boolean false 是否全局开启下拉刷新。 详见 Page.onPullDownRefresh
onReachBottomDistance Number 50 页面上拉触底事件触发时距页面底部距离,单位为px。 详见 Page.onReachBottom
disableScroll Boolean false 设置为 true 则页面整体不能上下滚动。 只在页面配置中有效,无法在 app.json中设置
disableSwipeBack Boolean false 禁止页面右滑手势返回 微信客户端 7.0.0

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

逻辑层App Service

小程序开发框架的逻辑层使用 JavaScript 引擎为小程序提供开发者 JavaScript 代码的运行环境以及微信小程序的特有功能。

逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。

逻辑层的JavaScript

  1. 小程序不是运行在Web的浏览器中,所以没有BOMDOM对象,就意味着没有documentwindow
  2. 在小程序中有一些额外的全局成员
    1. App 方法,用于定义应用实例对象
    2. Page 方法,用于定义页面对象
    3. getApp方法,用于获取全局应用程序实例对象
    4. getCurrentPages方法,用于获取当前页面的调用栈,
    5. 说明:历史栈指的是当前调用的页面和历史页面的栈,尝试打印console.log(getCurrentPage())打印出来是一个数组,意味着返回值是一个数组,然后this指向当前的页面,是当前页面的调用栈
    6. wx对象:丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力
    7. 每个页面有独立的作用域,并提供模块化能力。
    8. 小程序的JS是支持CommonJS规范的,也就是说可以通过require载入模块,通过module.exports导出模块,但不支持exports.xxx

视图层View

框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。

将逻辑层的数据反应成视图,同时将视图层的事件发送给逻辑层。

WXML(WeiXin Markup language) 用于描述页面的结构。

WXS(WeiXin Script) 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。

WXSS(WeiXin Style Sheet) 用于描述页面的样式。

组件(Component)是视图的基本组成单元。

WXML

WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。

数据绑定

将数据动态渲染到页面中

简单数据绑定

  1. 数据在哪?

    1. data:页面的初始数据,给页面供数据的,就是界面和逻辑之间的桥梁
    2. 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Page({
    ...
    data: {
    ...
    message: "hello wxxcx",
    ...
    }
    ...
    })
  2. 绑定到哪?

    1. 通过双大括号的形式,绑定数据到想要输出的位置
  3. 简单数据绑定

    1. 绑定给页面中的text文本节点
    2. 绑定给class,为元素添加样式或者拼接样式
    3. 以字面量的形式或者简单的逻辑运算符(简单的运算或者三元表达式等)直接输出
    4. 双大括号的语法
      1. innerHTML
      2. 元素的属性上
      3. 不能用在标签名和属性名上
    5. 注意:若判断布尔类型时,要将true或者false包裹在双大括号内进行解析,防止被JS误解为字符串

列表渲染

将数组中的数据在页面中循环渲染

  1. index.js文件的data中定义一个数组,数组中的每一个成员都是一个对象
  2. index.wxml中利用wx:for=""遍历输出,注意这里的wx:for中间不能有空格
1
2
3
4
5
person: [
{ name: 'zhangsan', age: 18, adult: true },
{ name: 'wangwu', age: 20, adult: true },
{ name: 'zhaoliu', age: 16, adult: false }
]
1
2
3
4
<view wx:for="{{ person }}">
<checkbox checked='{{ item.adult }}'>checkbox>
<text>{{ item.name }}text>
view>
  1. 如果全局属性中有一个item关键词,解决方法可以直接在循环的属性后面加上wx:for-item="项目名称缩写",那么下面遍历的时候也需要用你起的别名进行遍历,看下面示例
1
2
3
4
<view wx:for="{{ person }}" wx:for-item="wx">
<checkbox checked='{{ wx.adult }}'>checkbox>
<text>{{ wx.name }}text>
view>
  1. 拿序号,但若关键字冲突,可以通过wx:for-index="i"去拿,那么下面拿序号的时候,就要用
1
2
3
4
5
<view wx:for="{{ person }}" wx:for-item="wx" wx:for-index="i">
<text>{{ i }}text>
<checkbox checked='{{ wx.adult }}'>checkbox>
<text>{{ wx.name }}text>
view>
  1. 另外wx:for的值在下面是可以点出来legth值的,我在代码中试了试
1
2
3
4
5
6
<view wx:for="{{ person }}" wx:for-item="wx" wx:for-index="i">
<text>{{ i }}text>
<checkbox checked='{{ wx.adult }}'>checkbox>
<text>{{ wx.name }}text>
<text>{{ person.length }}text>
view>
  1. wx:for 也可以嵌套,下边是一个九九乘法表 ,我们将这个乘法口诀代码粘贴到自己的测试项目中看一下
1
2
3
4
5
<view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="i">
<view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="j">
<view wx:if="{{i <= j}}">{{i}} * {{j}} = {{i * j}}view>
view>
view>
  1. 渲染一个包含多节点的结构块: 可以将 wx:for 用在标签上
1
2
3
4
<block wx:for="{{[1, 2, 3]}}">
<view>{{index}}:view>
<view>{{item}}view>
block>
  1. 使用 wx:key 来指定列表中项目的唯一的标识符
    1. 如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如中的输入内容,的选中状态)
    2. wx:key 的值以两种形式提供
      1. 作用:当数据发生改变时,快速定位更新的值,防止顺序错乱
      2. 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
      3. 保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字 ,如当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率
      4. 如不提供 wx:key,会报一个 warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。
      5. 示例:
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
34
35
36
37
38
39
Page({
data: {
objectArray: [
{id: 5, unique: 'unique_5'},
{id: 4, unique: 'unique_4'},
{id: 3, unique: 'unique_3'},
{id: 2, unique: 'unique_2'},
{id: 1, unique: 'unique_1'},
{id: 0, unique: 'unique_0'},
],
numberArray: [1, 2, 3, 4]
},
switch(e) {
const length = this.data.objectArray.length
for (let i = 0; i < length; ++i) {
const x = Math.floor(Math.random() * length)
const y = Math.floor(Math.random() * length)
const temp = this.data.objectArray[x]
this.data.objectArray[x] = this.data.objectArray[y]
this.data.objectArray[y] = temp
}
this.setData({
objectArray: this.data.objectArray
})
},
addToFront(e) {
const length = this.data.objectArray.length
this.data.objectArray = [{id: length, unique: 'unique_' + length}].concat(this.data.objectArray)
this.setData({
objectArray: this.data.objectArray
})
},
addNumberToFront(e) {
this.data.numberArray = [this.data.numberArray.length + 1].concat(this.data.numberArray)
this.setData({
numberArray: this.data.numberArray
})
}
})
1
2
3
4
5
6
7
8
9
10
<switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;">
{{item.id}}
switch>
<button bindtap="switch">Switchbutton>
<button bindtap="addToFront">Add to the frontbutton>

<switch wx:for="{{numberArray}}" wx:key="*this" style="display: block;">
{{item}}
switch>
<button bindtap="addNumberToFront">Add to the frontbutton>
  1. 注意:wx:for="string"的时候,会把字符串解析为数组,例如下面两个等价的代码
1
2
3
<view wx:for="hello">{{item}}view>
// 等同于
<view wx:for="{{ ['h', 'e', 'l', 'l', 'o'] }}">{{item}}view>

​2. 注意:花括号和引号之间如果有空格,将最终被解析成为字符串

1
2
3
<view wx:for="{{[1,2,3]}} ">{{item}}view>
// 等同于
<view wx:for="{{[1,2,3] + ' '}}">{{item}}view>

条件渲染

  1. 当判断是否需要去渲染一个代码块的时候,就需要用到wx:if , 当需要判断是否添加一个代码块的时候,要用到wx:elif或者wx:else

示例:用在wx:for章节的代码,跟着后面添加了几句判断

1
2
3
<view wx:if="{{ person.length > 5 }}">2view>
<view wx:elif="{{ person.length < 5 }}">3view>
<view wx:else>1view>
  1. 如果要一次性判断多个组件标签,可以使用一个 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。
1
2
3
4
<block wx:if="{{true}}">
<view>view1view>
<view>view2view>
block
  1. 注意 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。
  2. wx:ifVShidden

因为 wx:if 之中的模板也可能包含数据绑定,所以当 wx:if 的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。

同时 wx:if 也是惰性的,如果在初始渲染条件为 false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。

相比之下,hidden 就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。

一般来说,wx:if 有更高的切换消耗而 hidden 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则 wx:if 较好。

模板

WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。

定义模板

使用 name 属性,作为模板的名字。然后在