2.7.4 逻辑层文件
在微信小程序中,逻辑层对从后台接收到的数据进行加工处理,并将其发送给视图层, 与此同时还要接收视图层的事件反馈。但小程序中的 JavaScript 与原生 JavaScript 并不完全 一样,最显著的一点就是由于小程序框架的逻辑层并非运行在浏览器中,因此 JavaScript 在 Web 中的一些功能(如 window、document 等)无法使用。另外,小程序还依托微信强大的 生态能力,在原生 JavaScript 的基础上做了一些方便小程序开发者的改进,主要体现在以下 几点。
• 增加 App()和 Page()方法,进行程序注册和页面注册。
• 增加 getApp()和 getCurrentPages()方法,分别用来获取 App 实例和当前页面栈。
• 提供丰富的 API,如微信用户数据、扫一扫、微信支付等。
• 提供模块化能力,每个页面均有其独立的作用域。
每个小程序都需要在 app.js 中通过调用 App()方法注册小程序实例,用来绑定生命周期 函数、错误监听函数和页面不存在监听函数等函数,该方法必须调用且只能调用一次,否 则会出现无法预期的后果。对于 20210116_demo 项目,app.js 中的默认代码如代码清单 2-59 所示。
代码清单 2-59
// app.jsApp({ onLaunch() { // 展示本地存储能力constlogs=wx.getStorageSync('logs') || [] logs.unshift(Date.now()) wx.setStorageSync('logs', logs) // 登录wx.login({ success: res=> { // 发送 res.code 到后台换取 openId、sessionKey 与 unionId } }) // 获取用户信息wx.getSetting({ success: res=> { if (res.authSetting['scope.userInfo']) { // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹出对话框wx.getUserInfo({ success: res=> { // 可以将 res 发送给后台解码出 unionIdthis.globalData.userInfo=res.userInfo// 因为 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回// 所以此处加入 callback 以防止这种情况if (this.userInfoReadyCallback) { this.userInfoReadyCallback(res) } } }) } } }) }, globalData: { userInfo: null } })
代码清单 2-56 在 App()函数内部定义了 onLaunch()函数。该函数实现了两个功能。第一个功能 是通过wx.getStorageSync()函数获取每次小程序启动时的13 位时间戳,并通过wx.setStorageSync()函 数将该时间戳存储在日志(log)中,然后在 logs.js 文件中,通过引用 utils 文件夹中的 util.js 文件将对应的时间戳转换成标准时间格式,最后将其更新到 logs.wxml 页面。第二个功能是在 用户已经授权(即 scope.userInfo 值为 true)的情况下,获取用户信息(包括微信图像的网络地 址、所在城市/国家、性别、语言、昵称、省份)
接下来,我们通过 Page()来完成页面的注册。小程序中的每个页面都需要在页面对应的 js 文件中通过 Page 构造器进行注册,并指定页面的初始数据、生命周期函数回调、事件处理函 数等。index.js 中的默认代码如代码清单 2-60 所示。
代码清单 2-60
// index.js// 获取应用实例constapp=getApp() Page({ data: { motto: 'Hello World', userInfo: {}, hasUserInfo: false, canIUse: wx.canIUse('button.open-type.getUserInfo') }, // 事件处理函数bindViewTap() { wx.navigateTo({ url: '../logs/logs' }) }, onLoad() { if (app.globalData.userInfo) { this.setData({ userInfo: app.globalData.userInfo, hasUserInfo: true }) } elseif (this.data.canIUse) { // 因为 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回// 所以此处加入 callback 以防止这种情况app.userInfoReadyCallback=res=> { this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } } else { // 在没有 open-type=getUserInfo 版本时的兼容处理wx.getUserInfo({ success: res=> { app.globalData.userInfo=res.userInfothis.setData({ userInfo: res.userInfo, hasUserInfo: true }) } }) } }, getUserInfo(e) { console.log(e) app.globalData.userInfo=e.detail.userInfothis.setData({ userInfo: e.detail.userInfo, hasUserInfo: true }) } })
代码清单 2-60 首先通过 getApp()方法获取全局唯一的 App 实例,以方便我们拿到 App 上 的 userInfo 数据;然后在 Page()函数内部,分别定义了初始数据(data)、生命周期函数 (onLoad())、事件处理函数。当用户触发组件的 getUserInfo 事件时,小程序会将用户 图像、用户昵称通过 setData()方法更新到页面中;当触发组件的 bindViewTap 事件时, 小程序会跳转至日志页面。