文章目录

🌟前言
哈喽小伙伴们,上一期为大家讲解了一下小程序的自定义组件该如何去使用,也带着大家封装了一个带动画效果底部Tabbar组件,相信小伙伴们私底下也进行了尝试吧。今天给大家结合官方文档讲解一下小程序的架构,这篇文章主要以【逻辑层】为主,也希望大家静待我们的下篇【视图层】;让我们一起来看看吧🤘
🌟小程序架构
整个小程序框架系统分为两部分:逻辑层(App Service)
和 视图层(View)
。小程序提供了自己的视图层描述语言 WXML
和 WXSS
,以及基于 JavaScript
的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。
它们在两个线程里运行。
- 视图层使用
WebView
渲染,iOS
中使用自带WKWebView
,在Android
使用腾讯的 x5内核
(基于 Blink)运行。 - 逻辑层使用在
iOS
中使用自带的JSCore
运行,在Android
中使用腾讯的 x5 内核
(基于 Blink)运行。 开发工具
使用nw.js
同时提供了视图层和逻辑层的运行环境。
🌟逻辑层 App Service
逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。
开发者写的所有代码最终将会打包成一份 JavaScript 文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似 ServiceWorker
,所以逻辑层也称之为 App Service
。
在 JavaScript 的基础上,我们增加了一些功能,以方便小程序的开发:
- 增加
App
和Page
方法,进行程序注册和页面注册。 - 增加
getApp
和getCurrentPages
方法,分别用来获取App
实例和当前页面栈。 - 提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
- 提供模块化能力,每个页面有独立的作用域。
🌟注册小程序
详细的参数含义和使用请参考 App 参考文档 。
// app.js
App({
onLaunch (options) {
// Do something initial when launch.
},
onShow (options) {
// Do something when show.
},
onHide () {
// Do something when hide.
},
onError (msg) {
console.log(msg)
},
globalData: 'I am global data'
})
// xxx.js
const appInstance = getApp()
console.log(appInstance.globalData) // I am global data
🌟注册页面
🌟使用 Page 构造器注册页面
代码示例:
//index.js
Page({
data: {
text: "This is page data."
},
onLoad: function(options) {
// 页面创建时执行
},
onShow: function() {
// 页面出现在前台时执行
},
onReady: function() {
// 页面首次渲染完毕时执行
},
onHide: function() {
// 页面从前台变为后台时执行
},
onUnload: function() {
// 页面销毁时执行
},
onPullDownRefresh: function() {
// 触发下拉刷新时执行
},
onReachBottom: function() {
// 页面触底时执行
},
onShareAppMessage: function () {
// 页面被用户分享时执行
},
onPageScroll: function() {
// 页面滚动时执行
},
onResize: function() {
// 页面尺寸变化时执行
},
onTabItemTap(item) {
// tab 点击时执行
console.log(item.index)
console.log(item.pagePath)
console.log(item.text)
},
// 事件响应函数
viewTap: function() {
this.setData({
text: 'Set some data for updating view.'
}, function() {
// this is setData callback
})
},
// 自由数据
customData: {
hi: 'MINA'
}
})
详细的参数含义和使用请参考 Page 参考文档 。
🌟在页面中使用 behaviors
// my-behavior.js
module.exports = Behavior({
data: {
sharedText: 'This is a piece of data shared between pages.'
},
methods: {
sharedMethod: function() {
this.data.sharedText === 'This is a piece of data shared between pages.'
}
}
})
// page-a.js
var myBehavior = require('./my-behavior.js')
Page({
behaviors: [myBehavior],
onLoad: function() {
this.data.sharedText === 'This is a piece of data shared between pages.'
}
})
具体用法参见 behaviors 。
🌟使用 Component 构造器构造页面
代码示例:
Component({
data: {
text: "This is page data."
},
methods: {
onLoad: function(options) {
// 页面创建时执行
},
onPullDownRefresh: function() {
// 下拉刷新时执行
},
// 事件响应函数
viewTap: function() {
// ...
}
}
})
具体细节请阅读我们的上一篇博文 Component 构造器 章节。
🌟页面生命周期
下图说明了页面 Page 实例的生命周期。
🌟页面路由
🌟页面栈
路由方式 | 页面栈表现 |
---|---|
初始化 | 新页面入栈 |
打开新页面 | 新页面入栈 |
页面重定向 | 当前页面出栈,新页面入栈 |
页面返回 | 页面不断出栈,直到目标返回页 |
Tab 切换 | 页面全部出栈,只留下新的 Tab 页面 |
重加载 | 页面全部出栈,只留下新的页面 |
开发者可以使用 getCurrentPages()
函数获取当前页面栈。
🌟路由方式
路由方式 | 触发时机 | 路由前页面 | 路由后页面 |
---|---|---|---|
初始化 | 小程序打开的第一个页面 | onLoad, onShow | |
打开新页面 | 调用 API wx.navigateTo,使用组件 <navigator open-type="navigateTo"/> | onHide | onLoad, onShow |
页面重定向 | 调用 API wx.redirectTo,使用组件 <navigator open-type="redirectTo"/> | onUnload | onLoad, onShow |
页面返回 | 调用 API wx.navigateBack,使用组件<navigator open-type="navigateBack"> ,用户按左上角返回按钮 | onUnload | onShow |
Tab 切换 | 调用 API wx.switchTab使用组件 ,<navigator open-type="switchTab"/> ,用户切换 Tab | 各种情况请参考下表 | |
重启动 | 调用 API wx.reLaunch,使用组件 <navigator open-type="reLaunch"/> | onUnload | onLoad, onShow |
当前页面 | 路由后页面 | 触发的生命周期(按顺序) |
---|---|---|
A | A | Nothing happend |
A | B | A.onHide(), B.onLoad(), B.onShow() |
A | B(再次打开) | A.onHide(), B.onShow() |
C | A | C.onUnload(), A.onShow() |
C | B | C.onUnload(), B.onLoad(), B.onShow() |
C | B | D.onUnload(), C.onUnload(), B.onLoad(), B.onShow() |
D(从转发进入) | A | D.onUnload(), A.onLoad(), A.onShow() |
D(从转发进入) | B | D.onUnload(), B.onLoad(), B.onShow() |
注意事项
navigateTo
,redirectTo
只能打开非 tabBar 页面
。switchTab
只能打开tabBar
页面。reLaunch
可以打开任意页面。- 页面底部的
tabBar
由页面决定,即只要是定义为tabBar
的页面,底部都有tabBar
。 - 调用页面路由带的参数可以在目标页面的
onLoad
中获取。
🌟模块化
🌟模块化
注意:
exports
是module.exports
的一个引用,因此在模块里边随意更改exports
的指向会造成未知的错误。所以更推荐开发者采用 module.exports 来暴露模块接口,除非你已经清晰知道这两者的关系。- 小程序目前不支持直接引入
node_modules
, 开发者需要使用到node_modules
时候建议拷贝出相关的代码到小程序的目录中,或者使用小程序支持的npm
功能。
// common.js
function sayHello(name) {
console.log(`Hello ${name} !`)
}
function sayGoodbye(name) {
console.log(`Goodbye ${name} !`)
}
module.exports.sayHello = sayHello
exports.sayGoodbye = sayGoodbye
在需要使用这些模块的文件中,使用 require
将公共代码引入
var common = require('common.js')
Page({
helloMINA: function() {
common.sayHello('MINA')
},
goodbyeMINA: function() {
common.sayGoodbye('MINA')
}
})
🌟文件作用域
通过全局函数 getApp
可以获取全局的应用实例,如果需要全局的数据可以在 App()
中设置,如:
// app.js
App({
globalData: 1
})
// a.js
// The localValue can only be used in file a.js.
var localValue = 'a'
// Get the app instance.
var app = getApp()
// Get the global data and change it.
app.globalData++
// b.js
// You can redefine localValue in file b.js, without interference with the localValue in a.js.
var localValue = 'b'
// If a.js it run before b.js, now the globalData shoule be 2.
console.log(getApp().globalData)
🌟API
通常,在小程序 API 有以下几种类型:
🌟事件监听 API
代码示例:
wx.onCompassChange(function (res) {
console.log(res.direction)
})
🌟同步 API
代码示例:
try {
wx.setStorageSync('key', 'value')
} catch (e) {
console.error(e)
}
🌟异步 API
大多数 API 都是异步 API,如 wx.request
,wx.login
等。这类 API 接口通常都接受一个 Object 类型的参数
,这个参数都支持按需指定以下字段来接收接口调用结果:
🌟Object 参数说明
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
其他 | Any | - | 接口定义的其他参数 |
🌟回调函数的参数
属性 | 类型 | 说明 |
---|---|---|
errMsg | string | 错误信息,如果调用成功返回 ${apiName}:ok |
errCode | number | 错误码,仅部分 API 支持,具体含义请参考对应 API 文档,成功时为 0。 |
其他 | Any | 接口返回的其他数据 |
代码示例
wx.login({
success(res) {
console.log(res.code)
}
})
🌟异步 API 返回 Promise
注意事项
1.部分接口如 downloadFile
, request
, uploadFile
, connectSocket,
createCamera(小游戏)
本身就有返回值, 它们的 promisify
需要开发者自行封装。
2.当没有回调参数时,异步接口返回 promise
。此时若函数调用失败进入 fail
逻辑, 会报错提示 Uncaught (in promise)
,开发者可通过 catch
来进行捕获。
3.wx.onUnhandledRejection
可以监听未处理的 Promise
拒绝事件。
代码示例
// callback 形式调用
wx.chooseImage({
success(res) {
console.log('res:', res)
}
})
// promise 形式调用
wx.chooseImage().then(res => console.log('res: ', res))
🌟云开发 API
代码示例
wx.cloud.callFunction({
// 云函数名称
name: 'cloudFunc',
// 传给云函数的参数
data: {
a: 1,
b: 2,
},
success: function(res) {
console.log(res.result) // 示例
},
fail: console.error
})
// 此外,云函数同样支持promise形式调用
🌟结语
这篇为小伙伴们讲解小程序的架构之【逻辑层】,下期为大家讲解【视图层】的知识;水滴石穿,积少成多。各位小伙伴让我们 let’s be prepared at all times!