小程序交互
第一章:原生 API
小程序开发框架提供丰富的微信原生 API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等,几乎所有小程序的 API 都挂载在 wx 对象底下,例如:wx.chooseMedia()、wx.request(),wx 对象实际上就是小程序的宿主环境微信所提供的全局对象。
通常,在小程序 API 有以下几种类型:
① 事件监听 API:约定以 on 开头 API 用来监听某个事件是否触发,例如:wx.onThemeChange()。
② 同步 API:约定以 Sync 结尾的 API 都是同步 API,例如:wx.setStorageSync()。
③ 异步 API:大多数 API 都是异步 API,例如:wx.setStorage()。

异步 API 支持 callback & Promise 两种调用方式:
① 当接口参数 Object 对象中不包含 success/fail/complete 时将默认返回 Promise。
② 部分接口如 request, uploadFile 本身就有返回值,因此不支持 Promise 风格的调用方式,它们的 promisify 需要开发者自行封装。
一、网络请求
在微信小程序中,如果要发起 HTTPS 网络请求需要使用:wx.request(),语法如下:
wx.request({
// 接口地址,仅为示例,并非真实的接口地址
url: 'example.php',
// 请求的参数
data: { x: '' },
// 请求方式
method: 'GET|POST|PUT|DELETE',
header: {},
success (res) {
console.log(res.data)
},
fail(err) {
console.log(err)
},
// API 不管调用成功还是失败以后,都要执行的回调
complete: (res) => {
console.log(err)
}
})注意:wx.request() 请求的域名需要在小程序管理平台进行配置,如果小程序正式版使用 wx.request 请求未配置的域名,在控制台会有相应的报错。
但一般我们在开发阶段时,处于开发阶段的服务器接口可能还没部署到对应的域名下,经常会通过另一个域名来进行开发调试,考虑到这一点,为了方便开发者进行开发调试,开发者工具、小程序的开发版和小程序的体验版在某些情况下允许 wx.request 请求任意域名 (只适用于开发环境,只能在小程序开发者工具中生效) 。
将不校验合法域名、web-view (业务域名)、TLS 版本以及 HTTPS 证书勾选上:


二、界面交互
小程序还提供了一些用于界面交互的 API,如消息提示框、模态对话框、 loading 提示框等。
1. loading 提示框

loading 提示框常配合网络请求来使用,用于增加用户体验。
1)显示
wx.showLoading 显示加载提示框。
| 属性 | 类型 | 默认值 | 是否必填 | 说明 |
|---|---|---|---|---|
| title | string | 是 | 提示的内容 | |
| mask | boolean | false | 否 | 是否显示透明蒙层,防止触摸穿透 |
| success | function | 否 | 接口调用成功的回调函数 | |
| fail | function | 否 | 接口调用失败的回调函数 | |
| complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
语法如下:
wx.showLoading({
title: '提示内容', // 提示的内容
mask: true, // 是否显示透明蒙层,防止触摸穿透
success() {}, // 接口调用成功的回调函数
fail() {} // 接口调用失败的回调函数
})2)隐藏
wx.hideLoading 隐藏加载提示框。
wx.hideLoading()2. 消息提示框
消息提示框用来根据用户的某些操作来告知操作的结果,如退出成功给用户提示,提示删除成功等。
1)显示
wx.showToast(Object object)
此函数参数为一个对象,对象内容可以包含下列:
| 属性 | 类型 | 默认值 | 是否必填 | 说明 | 支持版本 |
|---|---|---|---|---|---|
| title | string | 是 | 提示的内容 | ||
| icon | string | 'success' | 否 | 图标 | |
| image | string | 否 | 自定义图标的本地路径,image 的优先级高于 icon | >= 1.1.0 | |
| duration | number | 1500 | 否 | 提示的延迟时间 | |
| mask | boolean | false | 否 | 是否显示透明蒙层,防止触摸穿透 | |
| success | function | 否 | 接口调用成功的回调函数 | ||
| fail | function | 否 | 接口调用失败的回调函数 | ||
| complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
语法如下:
wx.showToast({
title: '标题', // 提示的内容
duration: 2000, // 提示的延迟时间
mask: true, // 是否显示透明蒙层,防止触摸穿透
icon: 'success', // 图标
success() {}, // 接口调用成功的回调函数
fail() {} // 接口调用失败的回调函数
})2)隐藏
wx.hideToast(Object object)
隐藏窗口,此函数参数也算是一个对象,但此对象比较简单就包含三个函数。他一般用在我们显示一个提示框之后可能会留给用户一个“不再显示”按钮,用户点击之后提前结束显示。
| 属性 | 类型 | 默认值 | 是否必填 | 说明 |
|---|---|---|---|---|
| success | function | 否 | 接口调用成功的回调函数 | |
| fail | function | 否 | 接口调用失败的回调函数 | |
| complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
3. 模态对话框
wx.showModal(Object object)
此 API 函数可以显示一个交互的对话框。参数也是对象,具体如下:
| 属性 | 类型 | 默认值 | 是否必填 | 说明 |
|---|---|---|---|---|
| title | string | 是 | 提示的标题 | |
| content | string | 是 | 提示的内容 | |
| showCancel | boolean | true | 否 | 是否显示取消按钮 |
| cancelText | string | '取消' | 否 | 取消按钮的文字,最多 4 个字符 |
| cancelColor | string | #000000 | 否 | 取消按钮的文字颜色,必须是 16 进制格式的颜色字符串 |
| confirmText | string | '确定' | 否 | 确认按钮的文字,最多 4 个字符 |
| confirmColor | string | #3cc51f | 否 | 确认按钮的文字颜色,必须是 16 进制格式的颜色字符串 |
| success | function | 否 | 接口调用成功的回调函数 | |
| fail | function | 否 | 接口调用失败的回调函数 | |
| complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
此时表中的 title 和上文不一样,此时它是真的代表标题,然后 content 代表内容。当完成操作后会进入 success 函数。
在 success 函数中,会调入一个参数 res,也是一个对象。
| 属性 | 类型 | 说明 | 支持版本 |
|---|---|---|---|
| confirm | boolean | 为 true 时,表示用户点击了确定按钮 | |
| cancel | boolean | 为 true 时,表示用户点击了取消(用于 Android 系统区分点击蒙层关闭还是点击取消按钮关闭) | >= 1.1.0 |
此对象携带两个值也就是确定和取消,我们可以通过判断两个值的结果来判断用户做出什么操作。
推荐使用时不写 success 等回调,这样
wx.showModal(Object object)返回的就是 promise 对象,可以使用 await 关键字,代码更优雅。
三、本地存储
小程序中也能够像网页一样支持本地数据缓存,本地数据缓存是小程序存储在当前设备上硬盘上的数据,本地数据缓存有非常多的用途,我们可以利用本地数据缓存来存储用户在小程序上产生的操作,在用户关闭小程序重新打开时可以恢复之前的状态。我们还可以利用本地缓存一些服务端非实时的数据提高小程序获取数据的速度,在特定的场景下可以提高页面的渲染速度,减少用户的等待时间。其包含以下 8 个主要的 API。
| 同步 API | 异步 API | 作用 |
|---|---|---|
wx.setStorageSync(key, data) | wx.setStorage({key:xxx, data: xxx}) | 将数据存储在本地缓存中指定的 key 中 |
wx.getStorageSync(key) | wx.getStorage({key: xxx}) | 从本地缓存中同步获取指定 key 的内容 |
wx.removeStorageSync(key) | wx.removeStorage({key: xxx}) | 从本地缓存中移除指定 key |
wx.clearStorageSync() | wx.clearStorageSync() | 清理本地数据缓存 |

异步方式的 API,在调用的时候都需要传入对象类型的参数。
同步方式执行的 API 在使用时简洁比较好,缺点是同步会阻塞程序执行,执行效率上相较异步版本要差一些。
📌 注意事项
① 对象类型的数据,可以直接进行存储,无需使用
JSON.stringify转换。② 对象类型的数据存的时候没有使用转换,因此获取的时候也不需要使用
JSON.parse转换。
四、编程式路由
在小程序中实现页面的跳转,有两种方式:
① 声明式导航:navigator 组件。
② 编程式导航:使用小程序提供的 API。
wx.navigateTo():保留当前页面,跳转到应用内的某个页面,但是不能跳到 tabbar 页面。wx.redirectTo():关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。wx.switchTab():跳转到 tabBar 页面,路径后不能带参数。wx.reLaunch():关闭所有的页面,然后跳转到应用中某一个页面(不管跳转到 tabbar 还是非 tabbar 页面都可以)。wx.navigateBack():关闭当前页面,返回上一页面或多级页面。传递对象可以有个属性 delta,值为数字。
如果想携带参数,需要在跳转到的页面的 onLoad 钩子函数中通过形参进行接收。参数与路径之间使用 ? 分隔。
- 参数键与参数值用
=相连 - 不同参数用
&分隔 - 例如
path?key=value&key2=value2

五、事件监听
1. 上拉加载更多
上拉加载是小程序中常见的一种加载方式,当用户滑动页面到底部时,会自动加载更多的内容,以便用户继续浏览。
小程序中实现上拉加载的方式:
① 在 app.json 或者 page.json 中配置距离页面底部距离:onReachBottomDistance(默认 50px)。
② 在 页面.js 中定义 onReachBottom 事件监听用户上拉加载。
2. 下拉刷新
下拉刷新是小程序中常见的一种刷新方式,当用户下拉页面时,页面会自动刷新,以便用户获取最新的内容。
小程序中实现上拉加载更多的方式:
① 在 app.json 或者 page.json 中开启允许下拉,同时可以配置窗口、loading 样式等。
② 在 页面.js 中定义 onPullDownRefresh 事件监听用户下拉刷新。最好在这个回调函数里调用 wx.stopPullDownRefresh(),避免在下拉刷新以后,loading 效果有可能不会回弹回去。
3. 增强 scroll-view
1)scroll-view 上拉加载
lower-threshold:距底部 / 右边多远时,触发 scrolltolower 事件。值为数值。
bindscrolltolower:滚动到底部 / 右边时触发的函数。值为函数名。
enable-back-to-top:让滚动条返回顶部,iOS 点击顶部状态栏、安卓双击标题栏时,只支持竖向。值为布尔值。
2)scroll-view 下拉刷新
refresher-enabled:开启自定义下拉刷新。值为布尔值。
refresher-default-style:自定义下拉刷新默认样式。支持设置 black | white | none, none 表示不使用默认样式。
refresher-background:自定义下拉刷新区域背景颜色。
bindrefresherrefresh:自定义下拉刷新状态回调。
refresher-triggered:设置当前下拉刷新状态,(true 下拉刷新被触发,false 表示下拉刷新未被触发,用来关闭下拉效果) 。一般值为 data 选项中的某个属性。
第二章:自定义组件
小程序目前已经支持组件化开发,可以将页面中的功能模块抽取成自定义组件,以便在不同的页面中重复使用;
也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。
开发中常见的组件有两种:
① 公共组件:将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用。
② 页面组件:将复杂的页面拆分成多个低耦合的模块,有助于代码维护。
如果是公共组件,建议将其放在小程序的目录下的 components 文件夹中。
如果是页面组件,建议将其放在小程序对应页面目录下,当然你也可以放到页面的 components 文件夹中。
同时建议:一个组件一个文件夹,文件夹名称和组件名称保持一致。
📌 注意事项
① 自定义组件的需要在
json文件中需要配置component字段设为true。② 自定义组件通过
Component构造器进行构建,在构造器中可以指定组件的属性、数据、方法等。
一、组件定义与使用
创建自定义组件
以公共组件为例,创建的步骤如下:
1)在小程序的目录下新建 components 文件夹。
2)在 components 文件夹上,点击右键,选择新建文件夹 ,然后输入文件夹名称,我们建议文件夹的名称和组件的名称保持一致,这样方便后期对组件进行维护。我们这里新的的组件名称叫做:custom-checkbox。
3)在新建的组件文件夹上,点击右键,选择新建 Component,然后输入组件的名称,组件的名称建议和文件夹保持一致。
4)此时就已经创建了一个功能组件。

使用自定义组件
开发中常见的组件主要分为公共组件和页面组件两种,因此注册组件的方式也分为两种:
全局注册:在
app.json文件中配置usingComponents节点进行引用声明,注册后可在任意组件使用。局部注册:在页面的
json文件中配置usingComponents节点进行引用声明,只可在当前页面使用。

二、组件三大属性
1. 数据 / 方法
在组件的 .js 中,需要调用 Component 方法创建自定义组件,Component 中有以下两个属性:
data 数据:组件的内部数据。
methods 方法:在组件中事件处理程序需要写到 methods 中才可以。
2. 属性
属性 Properties 是指组件的对外属性,主要用来接收组件使用者传递给组件内部的数据,和 data 一同用于组件的模板渲染。
📌 注意事项
① 设置属性类型需要使用 type 属性,属性类型是必填项,value 属性为默认值。
② 属性类型可以为 String、Number、Boolean、Object、Array ,也可以为 null 表示不限制类型。
三、插槽
在使用基础组件时,可以给组件传递子节点传递内容,从而将内容展示到页面中,自定义组件也可以接收子节点内容。
只不过在组件模板中需要定义 <slot /> 节点,用于承载组件引用时提供的子节点。

默认情况下,一个组件的 wxml 中只能有一个 slot 。需要使用多 slot 时,可以在组件 js 中声明启用。
同时需要给 slot 添加 name 来区分不同的 slot,给子节点内容添加 slot 属性来将节点插入到 对应的 slot 中。

默认插槽与具名插槽可以同时使用。
四、组件样式
类似于页面,自定义组件拥有自己的 wxss 样式,组件对应 wxss 文件的样式,只对组件 wxml 内的节点生效。
1. 选择器使用注意事项
① app.wxss 或页面的 wxss 中使用了标签名(view)选择器(或一些其他特殊选择器)来直接指定样式。这些选择器会影响到页面和全部组件,通常情况下这是不推荐的做法。
② 组件和引用组件的页面不能使用 id 选择器 (#a)、属性选择器 ([a]) 和 标签名选择器,请改用 class 选择器。
③ 组件和引用组件的页面中使用后代选择器(.a .b)在一些极端情况下会有非预期的表现,如遇,请避免使用。
④ 子元素选择器(.a>.b)只能用于 view 组件与其子节点之间,用于其他组件可能导致非预期的情况。
⑤ 继承样式,如 font、color,会从组件外继承到组件内。
⑥ 除继承样式外, 全局中的样式、组件所在页面的的样式对自定义组件无效 (除非更改组件样式隔离选项) 。
2. 组件样式隔离
默认情况下,自定义组件的样式只受到自定义组件 wxss 的影响。除非以下两种情况:
1)app.wxss 或页面的 wxss 中使用了标签名(view)选择器(或一些其他特殊选择器)来直接指定样式,这些选择器会影响到页面和全部组件。通常情况下这是不推荐的做法。
2)指定特殊的样式隔离选项 styleIsolation。
Component({
options: {
styleIsolation: 'isolated'
}
})styleIsolation 选项它支持以下取值:
isolated表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(一般情况下的默认值)。apply-shared表示页面 wxss 样式或组件使用者 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面和组件使用者 wxss 样式。shared表示页面 wxss 样式或组件使用者 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响使用者、页面和其他设置了apply-shared或shared的自定义组件。
3. 小程序修改checkbox样式
在官方文档,找到官方提供的案例,审查元素,就能看到对应的类名。

📌 注意事项
① .custom-checkbox .wx-checkbox-input {}:复选框没有选中时默认的样式。
② .custom-checkbox .wx-checkbox-input-checked {}:复选框选中时默认的样式。
③ .custom-checkbox .wx-checkbox-input.wx-checkbox-input-checked:before {}:复选框选中时 √ 样式。
这几个类名,在全局样式文件、页面样式文件都可以对修改复选框样式。但是在自定义组件内部使用的时候,需要添加
styleIsolation: 'shared'属性。
4. 外部样式类
默认情况下,组件和组件使用者之间如果存在相同的类名不会相互影响。组件使用者如果想修改组件的样式,需要就解除样式隔离,但是解除样式隔离以后,在极端情况下,会产生样式冲突、CSS 嵌套太深等问题,从而给我们的开发带来一定的麻烦。
这时候就可以使用外部样式类。在使用组件时,组件使用者可以给组件传入 CSS 类名,通过传入的类名修改组件的样式。
如果需要使用外部样式类修改组件的样式,在 Component 中需要用 externalClasses 定义若干个外部样式类。
外部样式类的使用步骤
① 在 Component 中用 externalClasses 定义段定义若干个外部样式类。
② 自定义组件标签通过属性绑定的方式提供一个样式类,属性是 externalClasses 定义的元素,属性值是传递的类名。
③ 将接受到的样式类用于自定义组件内部。
举例
➡️ custom09.js
// components/custom09/custom09.js
Component({
// 组件接受的外部样式类
externalClasses: ['extend-class']
})➡️ custom09.wxml
<!-- 在同一个节点上,如果存在外部样式类 和 普通的样式类 -->
<!-- 两个类的优先级是未定义的 -->
<!-- 建议:在使用外部样式类的时,样式需要通过 !important 添加权重 -->
<view class="extend-class box">通过外部样式类修改组件的样式</view>➡️ custom09.wxss
.box {
color: lightseagreen;
}📌注意事项
在同一个节点上使用普通样式类和外部样式类时,两个类的优先级是未定义的。
因此需要添加 !important 以保证外部样式类的优先级。
五、数据监听器
数据监听器可以用于监听和响应任何属性和数据字段的变化。有时,需要在一些数据字段被 setData 设置时,需要执行一些操作。那么就可以使用 observers 数据监听器来实现。语法如下:
Component({
data: {
num: 10,
count: 1,
obj: { name: 'Tom', age: 10 },
arr: [1, 2, 3]
},
observers: {
// key 是需要检测数据
// value 是一个函数,函数接收一个形参作为参数,是最新的值
num: function(newNum) {
console.log(newNum)
},
// 数据监听器支持监听属性或内部数据的变化,可以同时监听多个
'num, count': function (newNum, newCount) {
console.log(newNum, newCount)
}
// 监听器可以监听子数据字段
'obj.age': function(newAge) {
console.log(newAge)
},
// 如果需要监听所有子数据字段的变化,可以使用通配符 **
'obj.**': function(newAge) {
console.log(newAge)
},
'arr[0]': function (val) {}
}
})六、组件间通信与事件
1. 父给子传值
父组件如果需要向子组件传递数据,只需要两个步骤:
① 在父组件 WXML 中使用数据绑定的方式向子组件传递动态数据。
② 子组件内部使用 properties 接收父组件传递的数据即可。
复选框组件案例
➡️ index.js
Page({
data: {
isChecked: true
},
// coding...
})➡️ index.wxml
<custom-checkbox
label="我已阅读并同意 用户协议 和 隐私协议"
position="right"
checked="{{ isChecked }}">
我已阅读并同意 用户协议 和 隐私协议 - 111
</custom-checkbox>➡️ components/custom-checkbox/custom-checkbox.js
Component({
properties: {
// coding...
// 复选框组件公共组件
// 需要再多个页面、在多个项目中进行使用
// 在使用的时候,有的地方希望默认是选中的效果,有的地方希望默认是没有被选中的效果
// 怎么处理 ?
// 首先让复选框默认还是没有被选中的效果
// 如果希望复选框默认被选中,这时候传递属性(checked=true)到复选框组件
+ checked: {
+ type: Boolean,
+ value: false
+ }
},
/**
* 组件的初始数据:用来定义当前组件内部所需要使用的数据
*/
data: {
isChecked: false
},
+ observers: {
+ // 如果需要将 properties 中的数据赋值给 data
+ // 可以使用 observers 进行处理
+ checked: function (newChecked) {
+ // console.log(newChecked)
+ this.setData({
+ isChecked: newChecked
+ })
+ }
+ },
/**
* 组件的方法列表:在组件中,所有的事件处理程序都需要写到 methods 方法中
*/
methods: {
// 更新复选框的状态
updateChecked () {
this.setData({
+ isChecked: !this.data.isChecked,
+ // checked: !this.properties.checked
// label: '在组件内部也可以修改 properties 中的数据'
})
// 在 JS 中可以访问和获取 properties 中的数据
// 但是一般情况下,不建议修改,因为会造成数据流的混乱
// console.log(this.properties.label)
// console.log(this.data.isChecked)
}
}
})➡️ components/custom-checkbox/custom-checkbox.wxml
<view class="custom-checkbox-container">
<view class="custom-checkbox-box {{ position === 'right' ? 'right' : 'left' }}">
<checkbox class="custom-checkbox" checked="{{ isChecked }}" bindtap="updateChecked" />
<view class="content">
<!-- 如果用户传递了 lable 属性,就展示 lable -->
<!-- 如果用户没有传递 lable 属性,就展示 子节点内容 -->
<text wx:if="{{ label !== '' }}">{{ label }}</text>
<slot wx:else />
</view>
</view>
</view>2. 子往父传值
子组件如果需要向父组件传递数据,可以通过小程序提供的事件系统实现传递传递,可以传递任意数据。
事件系统是组件间通信的主要方式之一,自定义组件可以触发任意的事件,引用组件的页面可以监听这些事件,流程如下:
① 自定义组件触发事件时,需要使用 triggerEvent 方法发射一个自定义的事件。
② 自定义组件标签上通过 bind 方法监听发射的事件。
复选框组件案例
➡️ components/custom-checkbox/custom-checkbox.js
Component({
/**
* 组件的方法列表:在组件中,所有的事件处理程序都需要写到 methods 方法中
*/
methods: {
// 更新复选框的状态
updateChecked () {
this.setData({
isChecked: !this.data.isChecked,
// label: '在组件内部也可以修改 properties 中的数据'
})
// 在 JS 中可以访问和获取 properties 中的数据
// 但是一般情况下,不建议修改,因为会造成数据流的混乱
// console.log(this.properties.label)
// console.log(this.data.isChecked)
+ // 目前复选框组件的状态是存储在复选框组件内部的、存储在自定义组件内部的
+ // 但是,在以后实际开发中,组件使用者、父组件有时候也需要获取到复选框内部的状态
+ // 怎么办 ?
+ // 这时候,自定义组件内部就需要发射一个自定义事件,
+ // 如果组件使用者、父组件需要使用数据,绑定自定义事件进行获取即可
+ this.triggerEvent('changechecked', this.data.isChecked)
}
}
})➡️ index.html
<custom-checkbox
label="我已阅读并同意 用户协议 和 隐私协议"
position="right"
checked="{{ isChecked }}"
class="getchild"
bind:changechecked="getData"
>
我已阅读并同意 用户协议 和 隐私协议 - 111
</custom-checkbox>➡️ index.js
Page({
data: {
isChecked: true
},
getData (event) {
console.log(event.detail)
if (event.detail) {
console.log('提交')
} else {
console.log('请同意协议!')
}
}
})3. 获取组件实例
如果前面两种方式不足以满足需要。
可在父组件里调用 this.selectComponent(),获取子组件的实例对象,就可以直接拿到子组件的任意数据和方法。调用时需要传入一个匹配选择器 selector,如:this.selectComponent(".my-component")。
复选框组件案例
➡️ index.html
<custom-checkbox
label="我已阅读并同意 用户协议 和 隐私协议"
position="right"
checked="{{ isChecked }}"
class="child"
id="child"
bind:changechecked="getData"
>
我已阅读并同意 用户协议 和 隐私协议 - 111
</custom-checkbox>
<button type="primary" plain bindtap="getChild">获取子组件实例对象</button>➡️ index.js
Page({
// coding...
// 获取子组件的实例对象
getChild () {
// this.selectComponent 方法获取子组件实例对象
// 获取到实例对象以后,就能获取子组件所有的数据、也能调用子组件的方法
const res = this.selectComponent('#child')
console.log(res.data.isChecked)
}
})七、组件相关的生命周期
1. 组件所在页面的生命周期
组件的生命周期函数需要在 lifetimes 字段内进行声明。
最重要的生命周期是 created attached detached 包含一个组件生命周期流程的最主要时间点。
| 定义段 | 描述 |
|---|---|
created | 在组件实例刚刚被创建时执行,注意此时不能调用 setData (还没有对模板解析)。通常情况下,这个生命周期只应该用于给组件 this 添加一些自定义属性字段。 |
attached | 在组件实例进入页面节点树时执行 (模板已经解析完毕,并且挂载到页面上) |
| ready | 在组件布局完成后执行 |
| moved | 在组件实例被移动到节点树另一个位置时执行 |
detached | 在组件实例被从页面节点树移除时执行 (组件被销毁了) |
2. 组件所在页面的生命周期
组件还有一些特殊的生命周期,这类生命周期和组件没有很强的关联。
主要用于组件内部监听父组件的展示、隐藏状态,从而方便组件内部执行一些业务逻辑的处理。
组件所在页面的生命周期有 4 个:show、hide、resize、routeDone,需要在 pageLifetimes 字段内进行声明。
3. 小程序生命周期总结
小程序冷启动,钩子函数执行的顺序。

保留当前页面 (navigate) 以及关闭当前页面 (redirect) 。

切后台以及切前台 (热启动) 。

八、拓展
1. 使用 Component 构造页面
Component 方法用于创建自定义组件。
小程序的页面也可以视为自定义组件,因此页面也可以使用 Component 方法进行创建,从而实现复杂的页面逻辑开发。
Component({
properties: {
id: String,
title: String
},
data: {
name: 'tom'
},
methods: {
// 更新 name
updateName() {
this.setData({
name: 'jerry'
})
},
onLoad (options) {
console.log(this.data.id)
console.log(this.data.title)
console.log(this.properties.id)
},
}
})📌 注意事项
① 要求对应 json 文件中包含 usingComponents 定义段。
② 页面使用 Component 构造器创建,需要定义与普通组件一样的字段与实例方法。
③ 页面 Page 中的一些生命周期方法(如 onLoad() 等以“on”开头的方法),在 Component 中要写在 methods 属性中才能生效。
④ 组件的属性 Properties 可以用于接收页面的参数,在 onLoad() 中可以通过 this.data 拿到对应的页面参数或者 options 形参。
2. behaviors
小程序的 behaviors 方法是一种代码复用的方式,可以将一些通用的逻辑和方法提取出来,然后在多个组件中复用,从而减少代码冗余,提高代码的可维护性。
如果需要 behavior 复用代码,需要使用 Behavior() 方法,每个 behavior 可以包含一组属性、数据、生命周期函数和方法。
组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用。
注册 behavior:
如果需要注册一个 behavior,需要借助 Behavior() 方法,接受一个 Object 类型的参数。
// my-behavior.js
module.exports = Behavior({
behaviors: [],
properties: {
myBehaviorProperty: {
type: String
}
},
data: {
myBehaviorData: 'my-behavior-data'
},
created: function () {
console.log('[my-behavior] created')
},
attached: function () {
console.log('[my-behavior] attached')
},
ready: function () {
console.log('[my-behavior] ready')
},
methods: {
myBehaviorMethod: function () {
console.log('[my-behavior] log by myBehaviorMehtod')
},
}
})使用 behavior:
// my-component.js
const myBehavior = require('my-behavior')
Component({
behaviors: [myBehavior]
// coding...
})组件和它引用的 behavior 中可以包含同名的字段,对这些字段的处理方法如下:
① 如果有同名的属性或方法,采用 “就近原则”,组件会覆盖 behavior 中的同名属性或方法。
② 如果有同名的数据字段且都是对象类型,会进行对象合并,其余情况会采用 “就近原则” 进行数据覆盖。
③ 生命周期函数和 observers 不会相互覆盖,会是在对应触发时机被逐个调用(先 behaviors,后组件内),也就是都会被执行。