# 逻辑层(App Service) > 官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/ 逻辑层使用 JavaScript 引擎运行,不在浏览器中,没有 `window`、`document` 等 Web API。 ## App() — 注册小程序 ```javascript App({ onLaunch(options) { // 小程序初始化时触发,全局只触发一次 // options.scene — 场景值 // options.query — 启动参数 // options.path — 启动页面路径 }, onShow(options) { // 小程序启动或从后台进入前台时触发 }, onHide() { // 小程序从前台进入后台时触发 }, onError(msg) { // 小程序发生脚本错误或 API 调用失败时触发 console.error(msg) }, onUnhandledRejection(res) { // 未处理的 Promise 拒绝事件 console.warn(res.reason, res.promise) }, onPageNotFound(res) { // 页面不存在时触发 wx.redirectTo({ url: 'pages/...' }) }, onThemeChange({ theme }) { // 系统主题变更(dark / light) }, globalData: { userInfo: null } }) ``` 获取 App 实例: ```javascript const app = getApp() console.log(app.globalData) ``` **注意**: - 不要在 `App()` 内调用 `getApp()`,使用 `this` 即可 - 不要在 `onLaunch` 时调用 `getCurrentPages()`,此时 page 还没有生成 ## Page() — 注册页面 ```javascript Page({ data: { text: 'Hello', array: [{ msg: '1' }, { msg: '2' }] }, // ===== 生命周期 ===== onLoad(options) { // 页面加载时触发,options 为页面路由参数 // 一个页面只会调用一次 }, onShow() { // 页面显示/切入前台时触发 }, onReady() { // 页面初次渲染完成时触发 // 一个页面只会调用一次,代表页面已可以和视图层交互 }, onHide() { // 页面隐藏/切入后台时触发(如 navigateTo 或底部 tab 切换) }, onUnload() { // 页面卸载时触发(如 redirectTo 或 navigateBack) }, // ===== 页面事件处理 ===== onPullDownRefresh() { // 下拉刷新(需在 json 中开启 enablePullDownRefresh) // 处理完后调用 wx.stopPullDownRefresh() }, onReachBottom() { // 上拉触底(可在 json 中设置 onReachBottomDistance) }, onShareAppMessage(res) { // 用户点击右上角转发 // res.from: 'button' 或 'menu' return { title: '自定义转发标题', path: '/pages/index/index', imageUrl: '' // 自定义图片路径 } }, onShareTimeline() { // 分享到朋友圈(基础库 2.11.3+) return { title: '', query: '', imageUrl: '' } }, onPageScroll(res) { // 页面滚动时触发,res.scrollTop 为垂直滚动距离(px) // 注意:频繁触发,避免在此做复杂操作 }, onResize(res) { // 页面尺寸变化时触发(如屏幕旋转) }, onTabItemTap(item) { // 当前是 tab 页时,点击 tab 时触发 // item.index / item.pagePath / item.text }, // ===== 自定义方法 ===== viewTap() { this.setData({ text: 'Set some data for updating view.' }) } }) ``` ### 页面生命周期顺序 ``` onLoad → onShow → onReady → [onHide → onShow] → onUnload ``` ### setData 详解 ```javascript // 基本用法 this.setData({ text: 'changed data' }) // 修改数组某一项 this.setData({ 'array[0].msg': 'changed' }) // 修改对象某个属性 this.setData({ 'object.key': 'value' }) // 带回调 this.setData({ text: 'new' }, function() { // setData 引起的界面更新渲染完毕后的回调 }) ``` **setData 性能注意事项**: - 数据量不宜过大(单次 setData 不超过 1MB,建议不超过 256KB) - 不要频繁调用(如 onPageScroll 中不要每次都 setData) - 只传需要更新的数据,不要整个 data 都传 - 后台页面不要 setData(页面 onHide 后避免 setData) ## 页面路由 框架以栈的形式维护当前所有页面,最多 10 层。 | 路由方式 | 触发时机 | 路由前页面 | 路由后页面 | |----------|----------|-----------|-----------| | 初始化 | 小程序打开第一个页面 | | onLoad, onShow | | 打开新页面 | wx.navigateTo / `` | onHide | onLoad, onShow | | 页面重定向 | wx.redirectTo / `` | onUnload | onLoad, onShow | | 页面返回 | wx.navigateBack / 用户左上角返回 | onUnload | onShow | | Tab 切换 | wx.switchTab / `` / 用户切换 Tab | | 各种情况 | | 重启动 | wx.reLaunch / `` | onUnload | onLoad, onShow | ```javascript // 保留当前页面,跳转到新页面(页面栈 +1) wx.navigateTo({ url: '/pages/detail/detail?id=1' }) // 关闭当前页面,跳转到新页面(页面栈不变) wx.redirectTo({ url: '/pages/detail/detail?id=1' }) // 关闭所有页面,打开某个页面 wx.reLaunch({ url: '/pages/index/index' }) // 跳转到 tabBar 页面,关闭其他所有非 tabBar 页面 wx.switchTab({ url: '/pages/index/index' }) // 返回上一页(delta 为返回的页面数) wx.navigateBack({ delta: 1 }) ``` ### 页面间通信(EventChannel) ```javascript // 页面 A wx.navigateTo({ url: '/pages/B/B', events: { // 监听来自 B 页面的事件 acceptDataFromOpenedPage(data) { console.log(data) } }, success(res) { // 向 B 页面发送数据 res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' }) } }) // 页面 B Page({ onLoad() { const eventChannel = this.getOpenerEventChannel() // 向 A 页面发送数据 eventChannel.emit('acceptDataFromOpenedPage', { data: 'from B' }) // 监听来自 A 页面的数据 eventChannel.on('acceptDataFromOpenerPage', (data) => { console.log(data) }) } }) ``` ## 模块化 ```javascript // common.js function sayHello(name) { console.log(`Hello ${name}!`) } module.exports.sayHello = sayHello // 使用 const common = require('common.js') common.sayHello('MINA') ``` **注意**: - 小程序不支持直接引入 `node_modules`,需使用 npm 构建或手动拷贝 - 每个文件有独立作用域,不同文件中可声明同名变量 - 通过 `getApp()` 获取全局数据 ## getCurrentPages() ```javascript const pages = getCurrentPages() const currentPage = pages[pages.length - 1] // 当前页面 const prevPage = pages[pages.length - 2] // 上一个页面 // 可以通过 prevPage.setData() 修改上一页数据(返回时生效) ``` ## 在线查询 如需更详细信息,可抓取: - App 参考:https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html - Page 参考:https://developers.weixin.qq.com/miniprogram/dev/reference/api/Page.html - 路由:https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/route.html