微信小程序学习记录——3.框架-逻辑层

1.逻辑层简介

小程序开发框架的逻辑层是使用JavaScript编写的。

逻辑层将数据进行处理后发送给视图层,同时接收视图层的事件反馈。

在 JavaScript 的基础上,微信做了一些修改,以方便地开发小程序。

  • 增加 AppPage 方法,进行程序和页面的注册。
  • 增加 getAppgetCurrentPages 方法,分别用来获取 App 实例和当前页面栈。
  • 提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
  • 每个页面有独立的作用域,并提供模块化能力。
  • 由于框架并非运行在浏览器中,所以 JavaScript 在 web 中一些能力都无法使用,如 documentwindow 等。
  • 开发者写的所有代码最终将会打包成一份 JavaScript,并在小程序启动的时候运行,直到小程序销毁。类似 ServiceWorker,所以逻辑层也称之为 App Service

2.注册程序

App()

App() 函数用来声明小程序。其接收 object 类型参数,其指定小程序的生命周期函数等。

object参数说明:

属性类型描述触发时机
onLaunchFunction生命周期函数–监听小程序初始化当小程序初始化完成时,会触发 onLaunch(全局只触发一次
onShowFunction生命周期函数–监听小程序显示当小程序启动,或从后台进入前台显示,会触发 onShow
onHideFunction生命周期函数–监听小程序隐藏当小程序从前台进入后台,会触发 onHide
onErrorFunction错误监听函数当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
其他Any开发者可以添加任意的函数或数据到 Object 参数中,用 this 可以访问

前台、后台定义: 当用户点击左上角“关闭”,或者按了设备 “Home” 键离开微信,小程序并没有直接销毁,而是进入了后台;

当再次进入微信或打开小程序,又会从后台进入前台。

**需要注意的是:**只有当小程序进入后台一定时间,或者系统资源占用过高,才会被真正的销毁。

关闭小程序: 当用户从扫一扫、转发等入口(场景值为1007, 1008, 1011, 1025)进入小程序,且没有置顶小程序的情况下退出,小程序会被销毁。(基础库版本1.1.0开始支持,1.4.0版本已改变规则不再适用

示例代码:

App({
  onLaunch: function(options) {
    // Do something initial when launch.
  },
  onShow: function(options) {
      // Do something when show.
  },
  onHide: function() {
      // Do something when hide.
  },
  onError: function(msg) {
    console.log(msg)
  },
  globalData: '赈川'
})

onLaunch,onShow参数

上文讲到App()函数,其中onLaunch, onShow参数有他们特定的回调参数

字段类型说明
pathString打开小程序的路径
queryObject打开小程序的query
sceneNumber打开小程序的场景值
shareTicketStringshareTicket
referrerInfoObject当场景为由从另一个小程序或公众号或App打开时,返回此字段
referrerInfo.appIdString来源小程序或公众号或App的 appId,详见下方说明
referrerInfo.extraDataObject来源小程序传过来的数据,scene=1037或1038时支持

以下场景支持返回 referrerInfo.appId

场景值场景appId 信息含义
1020公众号 profile 页相关小程序列表返回来源公众号 appId
1035公众号自定义菜单返回来源公众号 appId
1036App 分享消息卡片返回来源应用 appId
1037小程序打开小程序返回来源小程序 appId
1038从另一个小程序返回返回来源小程序 appId
1043公众号模板消息返回来源公众号 appId

getApp()

全局的 getApp() 函数可以用来获取到小程序实例。

// other.js
var appInstance = getApp()
console.log(appInstance.globalData) //我们之前在app.js中定义了globalData,故将会输出 '赈川'

注意:

  • App() 必须在 app.js 中申明,且不能申明多个。
  • 不要在定义于 App() 内的函数中调用 getApp() ,使用 this 就可以拿到 app 实例。
  • 不要在 onLaunch 的时候调用 getCurrentPages(),因为此时 page 还没有生成。
  • 通过 getApp() 获取实例之后,不要私自调用生命周期函数。

getCurrentPages():获取到页面栈的所有页面Page对象组成的数组

3.场景值

上一节中有提到过场景值,我们来了解一下什么是场景值。

场景值可用于统计用户来源,根据不同的来源做不同的引流活动等。

我们可以在 App 的 onlaunchonshow 中获取场景值,部分场景值下还可以获取来源应用、公众号或小程序的appId

基础库 1.1.0 开始支持,低版本需做兼容处理 (具体的兼容方法我们会在后继章节中介绍)

当前支持的场景值有:

场景值ID说明
1001发现栏小程序主入口
1005顶部搜索框的搜索结果页
1006发现栏小程序主入口搜索框的搜索结果页
1007单人聊天会话中的小程序消息卡片
1008群聊会话中的小程序消息卡片
1011扫描二维码
1012长按图片识别二维码
1013手机相册选取二维码
1014小程序模版消息
1017前往体验版的入口页
1019微信钱包
1020公众号 profile 页相关小程序列表
1022聊天顶部置顶小程序入口
1023安卓系统桌面图标
1024小程序 profile 页
1025扫描一维码
1026附近小程序列表
1027顶部搜索框搜索结果页“使用过的小程序”列表
1028我的卡包
1029卡券详情页
1030自动化测试下打开小程序
1031长按图片识别一维码
1032手机相册选取一维码
1034微信支付完成页
1035公众号自定义菜单
1036App 分享消息卡片
1037小程序打开小程序
1038从另一个小程序返回
1039摇电视
1042添加好友搜索框的搜索结果页
1043公众号模板消息
1044带 shareTicket 的小程序消息卡片
1047扫描小程序码
1048长按图片识别小程序码
1049手机相册选取小程序码
1052卡券的适用门店列表
1053搜一搜的结果页
1054顶部搜索框小程序快捷入口
1056音乐播放器菜单
1057钱包中的银行卡详情页
1058公众号文章
1059体验版小程序绑定邀请页
1064微信连Wi-Fi状态栏
1067公众号文章广告
1068附近小程序列表广告
1071钱包中的银行卡列表页
1072二维码收款页面
1073客服消息列表下发的小程序消息卡片
1074公众号会话下发的小程序消息卡片
1078连Wi-Fi成功页
1089微信聊天主界面下拉
1090长按小程序右上角菜单唤出最近使用历史
1092城市服务入口

Tip: 由于Android系统限制,目前还无法获取到按 Home 键退出到桌面,然后从桌面再次进小程序的场景值,对于这种情况,会保留上一次的场景值。

4.注册页面

Page()

Page() 函数用来注册一个页面。通过传入一个 object 参数,指定页面的初始数据、生命周期函数、事件处理函数等。

object 参数说明:

属性类型描述
dataObject页面的初始数据
onLoadFunction生命周期函数–监听页面加载
onReadyFunction生命周期函数–监听页面初次渲染完成
onShowFunction生命周期函数–监听页面显示
onHideFunction生命周期函数–监听页面隐藏
onUnloadFunction生命周期函数–监听页面卸载
onPullDownRefreshFunction页面相关事件处理函数–监听用户下拉动作
onReachBottomFunction页面上拉触底事件的处理函数
onShareAppMessageFunction用户点击右上角转发
onPageScrollFunction页面滚动触发事件的处理函数
onTabItemTapFunction当前是 tab 页时,点击 tab 时触发
其他Any开发者可以添加任意的函数或数据到 object 参数中,在页面的函数中用 this 可以访问

object 内容在页面加载时会进行一次深拷贝,需考虑数据大小对页面加载的开销

示例代码:

//index.js
Page({
  data: {
    text: "该数据将传递到页面,供页面使用。"
  },
  onLoad: function(options) {
    // Do some initialize when page load.
  },
  onReady: function() {
    // Do something when page ready.
  },
  onShow: function() {
    // Do something when page show.
  },
  onHide: function() {
    // Do something when page hide.
  },
  onUnload: function() {
    // Do something when page close.
  },
  onPullDownRefresh: function() {
    // Do something when pull down.
  },
  onReachBottom: function() {
    // Do something when page reach bottom.
  },
  onShareAppMessage: function () {
   // return custom share data when user share.
  },
  onPageScroll: function() {
    // Do something when page scroll
  },
  onTabItemTap(item) {
    console.log(item.index)
    console.log(item.pagePath)
    console.log(item.text)
  },
  // 事件处理程序.  viewTap: function() {
    this.setData({
      text: '设置一些数据来更新视图。'    }, function() {
      // this is setData callback
    })
  },
  // 自定义数据
  customData: {
    hi: 'MINA'
  }
})

以下内容你不需要立马完全弄明白,不过以后它会有帮助。

生命周期

下图说明了 Page 实例的生命周期。

20180525150618411

生命周期中的函数
  • onLoad (页面加载): 一个页面只会调用一次,可以在 onLoad 中获取打开当前页面所调用的 query 参数。
  • onShow (页面显示): 每次打开页面都会调用一次。
  • onReady (页面初次渲染完成): 一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互。对界面的设置如wx.setNavigationBarTitle请在onReady之后设置。
  • onHide (页面隐藏): 当navigateTo或底部tab切换时调用。
  • onUnload (页面卸载): 当redirectTo或navigateBack的时候调用。

onLoad参数

类型说明
Object其他页面打开当前页面所调用的 query 参数

初始化数据

初始化数据将作为页面的第一次渲染。data 将会以 JSON 的形式由逻辑层传至渲染层,所以其数据必须是可以转成 JSON 的格式,如字符串,数字,布尔值,对象,数组。

渲染层可以通过 WXML 对数据进行绑定。

WXML代码:

<view>{{text}}</view>
<view>{{array[0].msg}}</view>

JS代码:

Page({
  data: {
    text: '今天的天气:',
    array: [{msg: '晴'}, {msg: '阴'}]
  }
})

执行结果:

img

页面相关事件处理函数

  • onPullDownRefresh: 下拉刷新

    1. 监听用户下拉刷新事件。
    2. 需要在app.json的window选项中或页面配置中开启enablePullDownRefresh。
    3. 当处理完数据刷新后,wx.stopPullDownRefresh可以停止当前页面的下拉刷新。
  • onReachBottom: 上拉触底

    1. 监听用户上拉触底事件。
    2. 可以在app.json的window选项中或页面配置中设置触发距离onReachBottomDistance。
    3. 在触发距离内滑动期间,本事件只会被触发一次。
  • onPageScroll: 页面滚动

    1. 监听用户滑动页面事件。
    2. 参数为 Object,包含以下字段:
  • 字段类型说明
    scrollTopNumber页面在垂直方向已滚动的距离(单位px)
  • onShareAppMessage: 用户转发

    1. 只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮
    2. 用户点击转发按钮的时候会调用
    3. 此事件需要 return 一个 Object,用于自定义转发内容

自定义转发字段

字段说明默认值
title转发标题当前小程序名称
path转发路径当前页面 path ,必须是以 / 开头的完整路径

示例代码

Page({
  onShareAppMessage: function () {
    return {
      title: '自定义转发标题',
      path: '/page/user?id=888'
    }
  }
})

事件处理函数

除了初始化数据和生命周期函数,Page 中还可以定义一些特殊的函数,如事件处理函数。在渲染层可以在组件中加入事件绑定,当达到触发事件时,就会执行 Page 中定义的事件处理函数。

WXML代码:

<view bindtap="viewTap"> click me </view>

JS代码:

Page({
  viewTap: function() {
    console.log('翻滚的胖子~')
  }
})

这边给大家顺带介绍一个比较实用的函数 Page.prototype.route

基础库 1.2.0 开始支持,低版本需做兼容处理

route 字段可以获取到当前页面的路径。

setData()函数

Page.prototype.setData()

setData 函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data 的值(同步)。

setData() 参数格式
字段类型必填描述
dataObject这次要改变的数据
callbackFunction回调函数(仅支持1.5.0及以上版本)

object 以 key,value 的形式表示将 this.data 中的 key 对应的值改变成 value。 callback 是一个回调函数,在这次setData对界面渲染完毕后调用。

其中 key 可以非常灵活,以数据路径的形式给出,如 array[2].message,a.b.c.d,并且不需要在 this.data 中预先定义。

注意:

  1. 直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致。
  2. 单次设置的数据不能超过1024kB,请尽量避免一次设置过多的数据。
  3. 请不要把 data 中任何一项的 value 设为 undefined ,否则这一项将不被设置并可能遗留一些潜在问题。

示例代码:

WXML代码:

<!--index.wxml-->
<view>{{text}}</view>
<button bindtap="changeText"> Change normal data </button>
<view>{{num}}</view>
<button bindtap="changeNum"> Change normal num </button>
<view>{{array[0].text}}</view>
<button bindtap="changeItemInArray"> Change Array data </button>
<view>{{object.text}}</view>
<button bindtap="changeItemInObject"> Change Object data </button>
<view>{{newField.text}}</view>
<button bindtap="addNewField"> Add new data </button>

JS代码:

//index.js
Page({
  data: {
    text: 'init data',
    num: 0,
    array: [{text: 'init data'}],
    object: {
      text: 'init data'
    }
  },
  changeText: function() {
    // this.data.text = 'changed data'  // bad, it can not work
    this.setData({
      text: 'changed data'
    })
  },
  changeNum: function() {
    this.data.num = 1
    this.setData({
      num: this.data.num
    })
  },
  changeItemInArray: function() {
    // you can use this way to modify a danamic data path
    this.setData({
      'array[0].text':'changed data'
    })
  },
  changeItemInObject: function(){
    this.setData({
      'object.text': 'changed data'
    });
  },
  addNewField: function() {
    this.setData({
      'newField.text': 'new data'
    })
  }
})

执行结果:(结合代码观察text和num参数在经过了setData函数的设置后的变化)

img

5.路由

页面路由

在小程序中所有页面的路由全部由框架进行管理。

页面栈

框架以栈的形式维护了当前的所有页面。 当发生路由切换的时候,页面栈的表现如下:

路由方式页面栈表现
初始化新页面入栈
打开新页面新页面入栈
页面重定向当前页面出栈,新页面入栈
页面返回页面不断出栈,直到目标返回页,新页面入栈
Tab 切换页面全部出栈,只留下新的 Tab 页面
重加载页面全部出栈,只留下新的页面

getCurrentPages()

getCurrentPages() 函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面。

Tip:不要尝试修改页面栈,会导致路由以及页面状态错误。

路由方式

对于路由的触发方式以及页面生命周期函数如下:

路由方式触发时机路由前页面路由后页面
初始化小程序打开的第一个页面onLoad, onShow
打开新页面调用 API wx.navigateTo 或使用组件 onHideonLoad, onShow
页面重定向调用 API wx.redirectTo 或使用组件 onUnloadonLoad, onShow
页面返回调用 API wx.navigateBack 或使用组件或用户按左上角返回按钮onUnloadonShow
Tab 切换调用 API wx.switchTab 或使用组件 或用户切换 Tab各种情况请参考下表
重启动调用 API wx.reLaunch 或使用组件 onUnloadonLoad, onShow

Tab 切换对应的生命周期(以 A、B 页面为 Tabbar 页面,C 是从 A 页面打开的页面,D 页面是从 C 页面打开的页面为例):

当前页面路由后页面触发的生命周期(按顺序)
AANothing happend
ABA.onHide(), B.onLoad(), B.onShow()
AB(再次打开)A.onHide(), B.onShow()
CAC.onUnload(), A.onShow()
CBC.onUnload(), B.onLoad(), B.onShow()
DBD.onUnload(), C.onUnload(), B.onLoad(), B.onShow()
D(从转发进入)AD.onUnload(), A.onLoad(), A.onShow()
D(从转发进入)BD.onUnload(), B.onLoad(), B.onShow()

Tips:

  • navigateTo, redirectTo 只能打开非 tabBar 页面。
  • switchTab 只能打开 tabBar 页面。
  • reLaunch 可以打开任意页面。
  • 页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
  • 调用页面路由带的参数可以在目标页面的onLoad中获取。

6.模块化

文件作用域

在 JavaScript 文件中声明的变量和函数只在该文件中有效;不同的文件中可以声明相同名字的变量和函数,不会互相影响。

通过全局函数 getApp() 可以获取全局的应用实例,如果需要全局的数据可以在 App() 中设置,如:

// app.js
App({
  globalData: 1
})
// a.js
// localValue只能用于文件a.js
var localValue = 'a'
// 获取应用程序实例。
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)

模块化

可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者 exports 才能对外暴露接口。

需要注意的是:

  • exportsmodule.exports 的一个引用,因此在模块里边随意更改 exports 的指向会造成未知的错误。所以更推荐开发者采用 module.exports 来暴露模块接口,除非你已经清晰知道这两者的关系。
  • 小程序目前不支持直接引入 node_modules , 开发者需要使用到 node_modules 时候建议拷贝出相关的代码到小程序的目录中。
// common.js
function sayHello(name) {
  console.log(`Hello ${name} !`)
}
function sayGoodbye(name) {
  console.log(`Goodbye ${name} !`)
}

module.exports.sayHello = sayHello
exports.sayGoodbye = sayGoodbye

在需要使用这些模块的文件中,使用 require(path) 将公共代码引入

var common = require('common.js')
Page({
  helloMINA: function() {
    common.sayHello('MINA')
  },
  goodbyeMINA: function() {
    common.sayGoodbye('MINA')
  }
})

Tips

require 暂时不支持绝对路径

7.API简介

框架提供丰富的微信原生API,可以方便的调起微信提供的功能,如获取用户信息,本地存储,支付等。

说明:

  • wx.on开头的API是监听某个事件发生的API接口,接受一个CALLBACK函数作为参数。当该事件触发时,会调用CALLBACK函数。
  • 如未特殊约定,其他API接口都接受一个OBJECT作为参数。
  • OBJECT中可以指定success,fail,complete来接收接口调用结果。
参数名类型必填说明
successFunction接口调用成功的回调函数
failFunction接口调用失败的回调函数
completeFunction接口调用结束的回调函数(调用成功、失败都会执行)
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赈川

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值