第二章 小程序框架_逻辑层
2.1 逻辑层
小程序开发框架的逻辑层是基于JavaScript进行编写和实现的。在开发过程中写的所有代码,最终都被整合成一份JavaScript,在小程序启动的时候开始执行,直到小程序停止运行。
逻辑层主要用于数据处理和接受事件反馈。此外,小程序在JavaScript的基础上增加了许多功能,例如:
- 增加了App()和Page()方法,用于整个应用程序和单独页面的注册;
- 增加了getApp()和getCurrentPages()方法,分别用于获取整个应用实例和当前应用实例;
- 提供了众多微信自带的API,可以十分快捷地使用许多微信中自带的功能;
- 每个页面的作用域独立,并提供了模块化功能。
但是,由于微信小程序开发框架不在浏览器中运行,所以JavaScript与浏览器相关的一些功能无法使用。
2.1.1 注册程序
1.App()方法
小程序通过App(OBJECT)方法进行应用的注册,用其指定小程序的生命周期函数。该方法只能写在小程序根目录下,且只能有一个。OBJECT参数如下表所示:
属性 | 类型 | 描述 | 触发时机 | 备注 |
onLaunch() | Function | 生命周期函数,监听小程序的初始化 | 当小程序完成初始化时触发 | 全局只触发一次 |
onShow() | Function | 生命周期函数,监听小程序的显示 | 当小程序启动或从后台进入前台时触发 |
|
onHide() | Function | 生命周期函数,监听小程序的隐藏 | 当小程序从前台进入后台隐藏时触发 |
|
onError() | Function | 错误监听函数 | 当小程序发送脚本错误或API调用失败时触发 |
|
onPageNotFound | Function | 页面不存在函数 | 当小程序需要打开的页面不存在时触发 |
|
其他自定义函数 | Any | 可以添加自定义名称的函数或数据到OBJECT参数中 |
| 用this访问 |
App()内的函数都为可选函数,一个全套的生命周期函数代码结构如下图所示:
其中,onLaunch(),onShow(),onError()在触发时都会返回参数,onLaunch和onShow返回的参数名称完全相同,具体如下表所示:
字段 | 类型 | 说明 |
path | String | 打开小程序的路径 |
query | Object | 打开小程序的query |
scene | Number | 打开小程序的场景值 |
shareTicket | String | 小程序被转发时会生成一个shareTicket,打开被转发的小程序页面可以获得该参数 |
referrerInfo | Object | 当场景为从另一个小程序/公众号/App打开时返回此字段 |
referrerInfo.appId | String | 跳转前的小程序/公众号/App的appId |
referrerInfo.extraData | Object | 跳转前的小程序传来的数据,当scene为1037或1038时才有效 |
App()中也可以添加自定义的全局变量,如下所示:
2.onPageNotFound()方法
当需要打开的页面不存在时,微信会有一个原生模板的页面提示。若不希望使用默认的模板,则可以调用该方法。
该方法的具体参数如下表所示:
字段 | 类型 | 说明 |
path | String | 不存在页面的路径 |
query | Object | 打开不存在页面的query |
isEntryPage | Boolean | 是否为本次启动的首个页面 |
该方法的示例如下:
值得一提的是,若该方法的回调又重定向到一个不存在的页面,将直接重定向到原生模板,而不会再执行该方法。
3.getApp()方法
在小程序的其他JS文件里都可以使用getApp()方法获得小程序实例,例如在index.js中
var app=getApp()
console.log(app.globalData.userInfo)
这时候就可以获得app.js中保存的公共数据,并在console控制台打印输出。但是在app.js中不可以使用getApp(),而是直接用this关键词代替,如:
App({
globalData:{
userInfo:null
},
onLoad:function(options){
console.log(this.globalData.userInfo)
},
})
2.1.2 注册页面
每个页面的JS文件中通过Page(OBJECT)的方法进行页面注册,可以用于指定小程序页面的生命周期函数。Page()方法只能写在每个页面对应的JS文件中,且只能存在一个。OBJECT参数如下表所示:
属性 | 类型 | 说明 |
data | Object | 页面的初始数据 |
onLoad() | Function | 生命周期函数,监听页面的加载 |
onReady() | Function | 生命周期函数,监听页面初次渲染完成 |
onShow() | Function | 生命周期函数,监听页面的显示 |
onHide() | Function | 生命周期函数,监听页面的隐藏 |
onUnload() | Function | 生命周期函数,监听页面的写在 |
onPullDownRefresh() | Function | 页面相关事件处理函数,监听用户下拉动作 |
onReachBottom() | Function | 页面上拉触底事件的处理函数 |
onShareAppMessage() | Function | 用户单击右上角转发 |
onPageScroll() | Function | 页面滚动触发事件的处理函数 |
onTabItemTap() | Function | 若当前是tab页,单击tab时触发 |
其他 | Any | 在页面的函数中用this访问 |
当新建页面时会自动生成JS文件中的Page()方法,如下所示:
// pages/newPage.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
该方法与App()类似,同样也支持添加自定义变量,如:
// pages/newPage.js
Page({
myData:'123', //定义页面变量
onLoad:function(options){
console.log(this.myData) //用this调用页面变量
},
})
1.初始数据
Page()方法中默认生成的第一项就是data属性,该属性是页面初次渲染时的初始数据,必须是可以转换为JSON的类型,比如字符串、数字、数组、布尔值、对象等。可以通过WXML对数据进行绑定,如:
页面JS的代码:
Page({
data:{
msg01:'hello',
msg02:2020
}
})
对应WXML的代码:
<view>{{msg01}}{{msg02}}</view>
这时候,msg01和msg02会自动查找data中的初始数据,然后显示hello 2020的字样。
2.生命周期回调函数
默认生成的onLoad()、onShow()、onReady()、onHide()和onUnload()都属于也免得生命周期回调函数:
- onLoad():格式为onLoad(Object query),只在页面加载时触发一次。可以在该方法的参数中获取打开当前页面路径附带的参数。
- onShow():当页面显示或从后台切入前台时触发。
- onReady():页面初次渲染完成后触发,一个页面只会调用一次。
- onHide():页面隐藏/切入后台时触发。
- onUnload():页面卸载时触发。
3.页面事件处理函数
默认生成的onPullDownRefresh()、onReachBottom()、onShareAppMessage()以及未自动生成的onPageScroll()、onTabItemTap()都是页面时间处理函数。
- onPullDownRefresh():监听用户下拉刷新界面。需要在app.json的window选项中或页面配置中开启enablePullDownRefresh。
- onReachBottom():监听用户上拉触底时间。可以在app.json的window选项或页面配置中设置触发距离onReachBottomDistance,在触发距离内只会被触发一次。
- onPageScroll(OBJECT):监听用户滑动页面时间,OBJECT只能为scrollTop,为Number类型,表示页面在垂直方向已经滚动的距离,单位为px。
- onShareAppMessage(OBJECT):监听用户单界面内转发按钮(<button>按钮组件,其属性值为open-type=”share”)或右上角转发按钮,并自定义转发内容。OBJECT参数如下表所示:
参数 | 类型 | 说明 |
from | String | 转发事件来源(button:以页面内转发按钮;menu:右上角转发菜单) |
target | Object | 若from值为button,则target是触发这次转发事件的button,否则为undefined |
webViewUrl | String | 当页面中包含<web-view>组件时返回当前<web-view>的url |
该事件需要一个Object对象,用于自定义转发内容,返回内容如下表所示:
字段 | 说明 |
title | 转发标题,默认为当前小程序名称 |
path | 转发路径,默认为当前页面path,必须是以根目录/开头的完整路径 |
imageUrl | 自定义文件路径,可以是本地文件路径、代码包文件路径或网络图片路径,支持PNG和JPG文件,显示图片的长宽比为5:4. |
该方法示例代码如下:
Page({
onTabItemTap(item){
console.log(item.index)
console.log(item.pagePath)
console.log(item.text)
}
})
4.组件事件处理函数
Page()方法中还可以定义组件事件处理函数,在WXML页面的组件上添加事件绑定,当事件被触发时会主动执行Page()中对应的事件处理函数。
以绑定单击事件为例,在WXML中的代码如下:
<button bindtap="binTap">单击此处</button>
JS中的代码如下:
Page({
binTap:function(){
console.log('按钮被单击')
}
})
页面效果如下:
点击后反馈结果如下:
5.route
在Page()中可以使用this.route查看当前页面的路径地址,例如:
Page({
onShow:function(){
console.log(this.route)
}
})
效果如下
6.setData()
该方法在Page()中用来同步更新data中的属性值,也能异步更新相关数据到WXML界面上,参数说明如下:
字段 | 类型 | 说明 |
data | Object | 要更新的一个或多个数据,格式如下: {key1:value1,key2:value2,...,keyN:valueN} |
callback | Function | setData引起的界面更新渲染完毕后的回调函数 |
7.生命周期
小程序在被打开时会首先触发onLaunch(),然后调用onShow(),被切入后台会调用onHide(),下次被唤醒时再次调用onShow()。
onShow()调用完后进入小程序页面的生命周期,依次触发onLoad(),onShow(),onReady()这三个函数。直到页面关闭触发onUnload()。
★tab页面的相互切换和打开新页面都不算页面关闭,只是起到了隐藏的作用,只会触发onHide()。
2.1.3 页面路由
1.页面栈
在小程序中页面之间的切换路由均由框架进行统一管理,框架以栈的形式维护了当前的所有界面。页面发生路由切换时,页面栈的表现如下:
路由方式 | 页面栈的表现 |
初始化 | 新页面入栈 |
打开新页面 | 新页面入栈 |
页面重定向 | 当前页面出栈,新页面入栈 |
页面返回 | 页面不断出栈,直到目标返回页面 |
Tab切换 | 页面不断出栈,只留下新的tab页面 |
重加载 | 页面全部出栈,只留下新的页面 |
2.获取页面栈
使用getCurrentPages()方法可以获得当前页面栈的实例,以数组形式按栈的顺序给出。第一个元素为首页,最后一个元素为当前页面。
2.1.4 模块化
1.文件的作用域
任意JS文件中生命的的变量和函数只在该文件中有效。若需要进行数据共享,可以选择在app.js中定义全局变量,然后在其他JS文件里通过getApp()获取和更新。
2.模块的调用
也可以选择将公共JavaScript代码放在一个单独的JS文件中,作为共偶那个模块被其他JS文件调用。模块只能通过module.exports或者exports提供对外接口。
例如在units文件夹下创建公共JS文件common.js,代码为:
function sayHello(name){
console.log('Hello ${name}!')
}
function sayGoodbye(name){
console.log('Goodbye ${name}')
}
module.exports.sayHello=sayHello //推荐该种方式提供接口
exports.sayGoodbye=sayGoodbye
在页面JS文件中使用require可以引用common.js函数,并调用其中函数,代码如下:
var common=require('../../utils/common.js')
Pages({
hello:function(){
common.sayHello('2020')
},
goodbye:function(){
common.sayGoodbye('2019')
}
})
参考文献
[1] 周文洁.微信小程序开发零基础入门[M].清华大学出版社:北京,2019:50-60.
[2] 微信小程序官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/.