逻辑层
逻辑层,是事务逻辑处理的地方。对于微信小程序而言,逻辑层就是所有.js脚本文件的集合。微信小程序在逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。
在JavaScript的基础上,微信团队做了一些适当地修改,主要的修改包括:
■增加App和Page方法,进行程序和页面的注册。
■增加getApp和getCurrentPage方法,分别用于获取App实例和当前页面。
■提供丰富的API,如扫一扫、支付等微信特有能力。
■每个页面有独立的作用域,并提供模块化能力。
但同时,由于框架并非运行在浏览器中,所以JavaScript在Web中的一些能力都将无法使用,比如document、window等,这也给开发带来相应的挑战。
逻辑层的实现就是编写各个页面的.js脚本文件。开发者编写的所有代码最终将会打包成一份JavaScript,并在小程序启动的时候运行,直到小程序销毁。类似ServiceWorker,所以逻辑层也称为App Service。
注册程序~App()方法
在逻辑层,App()方法用来注册一个小程序。App()接受一个object参数,用于指定小程序的生命周期函数等。App()方法有且仅有一个,存在于app.js中。object参数说明参见表
参数 | 类型 | 描述 | 触发时机 |
---|---|---|---|
onLaunch | Function | 生命周期函数-监听小程序初始化 | 当小程序初始化完成时,会触发onLaunch,全局只触发一次 |
onShow | Function | 生命周期函数-监听小程序显示 | 当小程序启动,或从后台进入前台显示,会触发onShow |
onHide | Function | 生命周期函数-监听小程序隐藏 | 当小程序进入后台,会触发onHide |
onError | Function | 错误监听函数 | 当小程序发生脚本错误,或者API调用失败时,会触发onError并带上错误信息 |
其它 | Any | 开发者可以添加任意的函数或数据到Object参数中,用this可以访问 | 。。。 |
前台、后台:
- 用户当前界面运行或操作小程序时为前台;
- 当用户点击左上角关闭,或者按了设备Home键离开微信,小程序并没有直接销毁,而是进入了后台;
- 当再次进入微信或再次打开小程序,又会从后台进入前台。
- 销毁:只有当小程序进入后台一定时间,或者系统资源占用过高,才会被真正销毁。此时代表小程序的生命周期结束。
周期代码:
App({
onLaunch: function() { // 启动时执行的初始化工作 },
onShow: function() { // 小程序进入前台时执行的操作 },
onHide: function() { // 小程序进入后台时执行的操作 },
onError: function(msg) { console.log(msg) },
globalData: 'I am global data' })
微信团队为开发者提供了全局的getApp()函数,可以用来获取小程序实例。
// other.js var appInstance = getApp() console.log(appInstance.globalData) //I am global data
注意
■App()方法须在app.js中注册,且不能注册多个。
■不要在定义App()内的函数中调用getApp(),使用this就可以拿到App实例。
■通过getApp()获取实例之后,不要私自调用生命周期函数(如onLaunch、onShow、onHide等)。
注册页面~Page()方法
在逻辑层,Page()方法用来注册一个页面。Page()接受一个object参数,用于指定页面的初始数据、生命周期函数、事件处理函数等。Page()方法,每个页面有且仅有一个,存在于该页面的.js文件中。object参数说明参见表
参数 | 类型 | 描述 |
---|---|---|
data | Object | 页面的初始数据 |
onLoad | Function | 生命周期函数-监听页面加载 |
onReady | Function | 生命周期函数-监听页面初次渲染完成 |
onShow | Function | 生命周期函数-监听页面显示 |
onHide | Function | 生命周期函数-监听页面隐藏 |
onUnload | Function | 生命周期函数-监听页面卸载 |
onPullDownRefresh | Function | 页面相关事件处理函数-监听用户下拉动作 |
onReachBottom | Function | 页面上拉触底事件的处理函数 |
onShareAppMessage | Function | 用户点击右上角分享 |
其它 | Any | 开发者可以添加任意的函数或数据到Object参数中,用this可以访问 |
Page()方法示例代码如下:
// index.js
Page({
data: {
text: "This is page data."
},
onLoad: function(options) { // 页面加载时的初始化操作
},
onReady: function() { // 页面初次渲染完成时执行的操作
},
onShow: function() { // 页面显示时执行的操作
},
onHide: function() { // 页面隐藏时执行的操作
},
onUnload: function() { // 页面卸载/关闭时执行的操作
},
onPullDownRefresh: function() { // 用户在页面下拉时执行的操 作 },
onReachBottom: function() { // 到达页面底部时执行的操作
},
onReachBottom: function() { // 到达页面底部时执行的操作
},
onShareAppMessage: function() { // 用户分享时返回定制的分享 数据 },
// 事件处理
viewTap: function() {
this.setData({
text: 'Set some data for updating view.'
})
}
})
同样,微信团队为开发者提供了getCurrentPage()函数,用来获取当前页面的实例。
注意
不要在App()中进行onLaunch操作的时候调用getCurrentPage(),此时page还没有生成。
1.初始化数据
初始化数据将作为页面的第一次渲染。对象data将会以JSON的形式由逻辑层传至视图层,所以其数据必须是可以转成JSON的格式:字符串、数字、布尔值、对象、数组。
视图层可以通过WXML对数据进行绑定。
示例代码如下:
// wxml
// 渲染page()的数据
{{text}}
{{array[0].msg}}
//page.js
//page()中的初始化数据data
Page({
data:{
text:'init data',
array:[{msg:'1'},{msg:'2'}]
}
})
2.生命周期函数使用
onLoad是页面加载时执行的初始化操作:
■一个页面只会调用一次。
■参数可以获取wx.navigateTo和wx.redirectTo及中的query。
onShow是页面显示时执行的操作。每次打开页面都会调用一次。
onReady是页面初次渲染完成时执行的操作:
■一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互。
■对页面的设置(如wx.setNavigationBarTitle)请在onReady之后设置。
onHide是页面隐藏时执行的操作。当navigateTo或底部进行tab切换时调用。
onUnload是页面卸载时执行的操作。当进行redirectTo或navigateBack操作的时候调用。
3.页面相关事件处理函数
onPullDownRefresh是下拉刷新时执行的操作,例如:
■监听用户下拉刷新事件。
■需要在页面.json文件的window配置项中开启enablePullDownRefresh。
■当处理完数据刷新后,wx.stopPullDownRefresh可以停止当前页面的下拉刷新。onShareAppMessage是用户分享时返回定制的分享内容:
■只有定义了此事件处理函数,右上角菜单才会显示“分享”按钮。
■用户点击分享按钮的时候会调用。
■此事件需要return一个Object,用于自定义分享内容。
onShareAppMessage自定义分享字段如下:
字段 | 说明 | 默认值 |
---|---|---|
title | 分享标题 | 当前小程序名称 |
path | 分享路径 | 当前页面path,必须以/开头的完整路径 |
onShareAppMessage示例代码如下:
Page({
onShareAppMessage: function () {
return {
title: ’自定义分享标题’,
path: '/page/user? id=123'
}
}
})
4.事件处理函数
除了初始化数据和生命周期函数,Page()方法中还可以定义一些特殊的函数:事件处理函数。我们可在视图层通过对组件加入事件绑定,当满足触发事件时,就会执行Page()中定义的事件处理函数。
示例代码如下:
// // 绑定tap事件到view组件上,处理事件的函数名为viewTap click me // page.js Page({ // 定义一个viewTap事件处理函数 viewTap: function() { console.log('view tap') } })
5.页面数据设置及展现
在Page()中,我们要使用setData函数来将数据从逻辑层发送到视图层,同时改变对应的this.data的值。
注意
■this是包含它的函数作为方法被调用时所属的对象,在小程序中一般指调用页面。
■直接修改this.data无效,无法改变页面的状态,还会造成数据不一致。
■单次设置的数据不能超过1024KB,请尽量避免一次设置过多的数据。
setData()函数的参数接受一个对象。以“key, value”的形式表示将this.data中的key对应的值改变成value。其中key可以非常灵活,包括以数据路径的形式给出,如array[2].message, a.b.c.d,并且无须在this.data中预先定义。
示例代码如下:
// wxml
{{text}}
{{array[0].text}}
{{objc.text}}
{{newField.text}}
// index.js Page({ data: { text: 'init data', array: [{text: 'init data'}], object: { text: 'init data' } }, changeText: function() { //这样设置this.data.text = 'changed data’是不行的,会出错 this.setData({ text: 'changed data' }) }, changeItemInArray: function() { // 可以这样使用setData以修改动态的数据路径 this.setData({ 'array[0].text':'changed data' }) }, changeItemInObject: function(){ this.setData({ 'object.text': 'changed data' }); }, addNewField: function() { this.setData({ 'newField.text': 'new data' }) } })
6.页面栈及其实例获取
框架以栈的形式维护了当前的所有页面。当发生路由切换的时候,页面栈的表现如下:
路由方式 | 页面栈表现 |
---|---|
初始化 | 新页面入栈 |
打开新页面 | 新页面入栈 |
页面重定向 | 当前页面出栈,新页面入栈 |
页面返回 | 页面不断出栈,直到目标返回页,新页面入栈 |
Tab切换 | 当前页面出栈,新页面入栈 |
getCurrentPages()函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面。
注意
不要尝试修改页面栈,会导致路由以及页面状态错误。
7.理解页面的生命周期
Page与实例的生命周期:
从图中可以看到,左边是视图层(.wxml与.wxss文件),右边是逻辑层(.js文件)。页面初始化后,在整个生命周期中持续进行相应的业务数据准备、数据展现及响应事件处理、数据保存等,直到页面卸载。
8.页面的路由
在小程序中,所有页面的路由全部由框架进行管理,对于路由的触发方式以及页面生命周期函数参见表
路由方式 | 触发时机 | 路由后页面 | 路由前页面 |
---|---|---|---|
初始化 | 小程序打开的第一个页面 | onLoad、onShow | ... |
打开新页面 | 调用API wx.navigateTo或使用组件 |
onLoad、onShow | onHide |
页面重定向 | 调用API wx.redirectTo或使用组件 |
onLoad、onShow | onUnload |
页面返回 | 调用API wx.navigateBack或者用户按左上角返回按钮 | onShow | onUnload |
Tab切换 | 调用API wx.switchTab或者使用组件 |
第一次打开onLoad\onShow\否则onShow | onHide |
模块及调用
1.文件作用域
在页面的JavaScript(.js)脚本文件中声明的变量和函数只在该文件中有效;不同的文件中可以声明相同名字的变量和函数,不会互相影响。
通过全局函数getApp()可以获取全局的应用实例,如果需要全局的数据可以在App()中设置,例如:
// app.js App({ globalData: 1 }) // a.js
// 变量localValue只在a.js文件中有效
var localValue = 'a'
// 获取App实例
var app = getApp()
// 获取全局数据值并修改
app.globalData++ // b.js
// 可以在b.js文件中重新定义变量localValue,这并不会影响a.js文件中的localValue
var localValue = 'b'
// 若a.js在b.js运行,那么这里的globalData就应是2
console.log(getApp().globalData)
2.模块化
我们可以将一些公共的代码抽离成为一个单独的js脚本文件,作为一个模块。
注意
模块只有通过module.exports才能对外暴露接口以供其他.js文件引入使用。
示例代码如下:
//common.js
function sayHello(name){
console.log('Hello'+name+'!')
}
module.exports = {
sayHello:sayHello
}
在需要使用这些模块的.js文件中,使用require(path)将公共代码引入。
示例代码如下:
//call.js
var common = require('common.js')
Page({
helloMINA:function(){
common.sayHello('MINA')
}
})
微信原生API
微信原生的API共有八大类:网络API、媒体API、文件API、数据缓存API、位置API、设备API、界面API以及微信开放接口。
在使用这些微信原生API之前,我们先看看注意事项:
■wx.on开头的API是监听某个事件发生的API接口,接受一个回调(CALLBACK)函数作为参数。当该事件触发时,会调用该回调函数。
■如未特殊约定,其他API接口都接受一个OBJECT作为参数。
■object中可以指定success、fail、complete来接收接口调用结果(见下表)
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
Success | Function | 否 | 接口调用成功的回调函数 |
Fail | Function | 否 | 接口调用失败的回调函数 |
Complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
微信原生API列表名称及主要用途:
网络API:
名称 | 主要用途 |
---|---|
wx.request | 发起网络请求 |
wx.uploadFile | 上传文件 |
wx.downloadFile | 下载文件 |
wx.connectSocket | 创建WebSocket连接 |
wx.onSocketOpen | 监听WebSocket打开 |
wx.onSocketError | 监听WebSocket错误 |
wx.sendSocketMessage | 发送WebSocket消息 |
wx.onSocketMessage | 接收WebSocket消息 |
wx.closeSocket | 关闭WebSocket连接 |
wx.onSocketClose | 监听WebSocket关闭 |
媒体API:
名称 | 主要用途 |
---|---|
wx.chooseImage | 从相册选择图片或拍照 |
wx.previewImage | 预览图片 |
wx.getImageInfo | 获取图片信息 |
wx.startRecord、wx.StopRecord | 开始录音、结束录音 |
wx.playVoice、wx.pauseVoice、wx.stopVoice | 播放语音、暂停播放语音、结束播放语音 |
wx.createAudioContext | 创建并返回audio的上下文对象 |
wx.getBackgroundAudioPlayState | 获取音乐播放状态 |
wx.playBackgroundAudio | 播放音乐 |
wx.pauseBackgroundAudio | 暂停播放音乐 |
wx.seekBackgroundAudio | 控制音乐播放进度 |
wx.stopBackgroundAudio | 停止播放音乐 |
wx.onBackgroundAudioPlay | 监听音乐开始播放 |
wx.onBackgroundAudioPause | 监听音乐暂停 |
wx.onBackgroundAudioStop | 监听音乐结束 |
wx.chooseVideo | 从相册选择视频或者拍摄 |
wx.createVideoContext | 创建并video的上下文对象 |
文件API:
名称 | 主要用途 |
---|---|
wx.saveFile | 保存文件 |
wx.getSavedFileList | 获取本地已保存的文件列表 |
wx.getSavedFileInfo | 获取本地文件的文件信息 |
wx.removeSavedFile | 删除本地储存的文件 |
wx.openDocument | 新开页面打开文档,支持格式doc、xls、ppt、doc、xlsx、pptx |
数据缓存API:
名称 | 主要用途 |
---|---|
wx.getStorge(wx.getStorgeSync) | 异步获取本地数据缓存(同步) |
wx.setStorge(wx.setStorgeSync) | 异步设置本地数据缓存(同步) |
wx.removeStorge(wx.removeStorgeSync) | 异步移除本地指定key(同步) |
wx.clearStorge(wx.clearStorgeSync) | 异步清理本地数据缓存(同步) |
位置API:
名称 | 主要用途 |
---|---|
wx.getLocation | 获取当前位置 |
wx.chooseLocation | 打开内置地图选择位置 |
wx.openLocation | 打开内置地图 |
wx.createMapContext | 创建map的上下文对象 |
设备信息API:
名称 | 主要用途 |
---|---|
wx.getNetworkType | 获取网络类型 |
wx.getSystemInfo(wx.getSystemInfoSync) | 获取系统信息(同步) |
wx.onAccelerometerChange | 监听重力感应数据 |
wx.onCompassChange | 监听罗盘数据 |
wx.makePhoneCall | 调起拨打电话 |
wx.scanCode | 调起客户端扫码界面 |
界面API:
名称 | 主要用途 |
---|---|
wx.showToast、wx.hideToast | 显示消息提示框、隐藏消息提示框 |
wx.showModal | 显示状态弹框 |
wx.showActionSheet | 显示操作菜单 |
wx.setNavigationBarTitle | 设置当前页面标题 |
wx.showNavigationBarLoading | 显示导航条加载动画 |
wx.hideNavigationBarLoading | 隐藏导航条加载动画 |
wx.navigationTo、wx.mavigationBack | 新窗口打开页面、返回页面 |
wx.redirectTo | 原窗口打开页面 |
wx.switchTab | 跳转到Tab页面 |
wx.createAnimation | 动画 |
wx.creatCanvasContext | 创建canvas绘图上下文 |
wx.createContext | 创建绘图上下文 |
wx.drawCanvas | 绘图 |
wx.canvasToTempFilePath | 保护画布内容 |
wx.hideKeyboard | 隐藏键盘 |
Page.onPullDownRefresh | 监听页面用户下拉刷新 |
wx.stopPullDownRefresh | 停止下拉刷新动画 |
开放API:
名称 | 主要用途 |
---|---|
wx.login | 登陆 |
wx.getUserInfo | 获取用户信息 |
wx.requestPayment | 发起微信支付 |