1.注册小程序
每个小程序都需要在 app.js 中调用 App 方法注册小程序实例,必须调用且只能调用一次。
函数:App(Object obj)
参数:一个Object类型,实际是一个事件回调函数或变量列表。
例如:
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'})
(1) onLaunch(Object object)
生命周期回调——小程序初始化完成后调用。
回调参数object与wx.getLaunchOptionsSync()函数的返回值一致。
onLoad: function (options) { var obj = wx.getLaunchOptionsSync() console.log('启动小程序的路径:',obj.path) console.log('启动小程序的场景值:', obj.scene) console.log('启动小程序的 query 参数:', obj.query) console.log('来源信息:', obj.shareTicket) console.log('来源信息参数appId:', obj.referrerInfo.appId) console.log('来源信息传过来的数据:', obj.referrerInfo.extraData) }
(2) onShow(Object object)
小程序启动,或从后台进入前台显示时触发。也可以使用 wx.onAppShow 绑定监听。
(3) onHide()
小程序从前台进入后台时触发。也可以用wx.onAppHide(function callback)绑定监听切到后台。
(4) onError(String error)
小程序发生脚本错误或 API 调用报错时触发。
也可以使用 wx.onError(function callback)绑定监听。
(5)onPageNotFound(Object object)
小程序要打开的页面不存在时触发。
也可以使用 wx.onPageNotFound(function callback)绑定监听。
App({ onPageNotFound(res) { wx.redirectTo({ url: 'pages/...' }) // 如果是 tabbar 页面,请使用 wx.switchTab }})
开发者可以在回调中进行页面重定向,但必须在回调中同步处理,异步处理(例如
setTimeout
异步执行)无效。若开发者没有调用 wx.onPageNotFound 绑定监听,也没有声明
App.onPageNotFound
,当跳转页面不存在时,将推入微信客户端原生的页面不存在提示页面。如果回调中又重定向到另一个不存在的页面,将推入微信客户端原生的页面不存在提示页面,并且不再第二次回调。
(6) 数据变量
如例子中的globalData,可以直接用this.globalData调用。
2.获取小程序实例
通过 getApp 方法获取到全局唯一的 App 实例,获取App上的数据或调用开发者注册在 App 上的函数。
// xxx.jsconst appInstance = getApp()console.log(appInstance.globalData) // I am global data
3.注册页面
对于小程序中的每个页面,都需要在页面对应的 js
文件中进行注册,指定页面的初始数据、生命周期回调、事件处理函数等。
(1)使用 Page 构造器注册页面
//index.jsPage({ data: { text: "This is page data." }, onLoad: function(options) { // 页面加载时触发。一个页面只会调用一次 }, onShow: function() { // 页面显示/切入前台时触发 }, onReady: function() { // 页面初次渲染完成时触发。一个页面只会调用一次, // 代表页面已经准备妥当,可以和视图层进行交互 // 注意:对界面内容进行设置的 API 如wx.setNavigationBarTitle,请在onReady之后进行 }, onHide: function() { // 页面从前台变为后台时执行 }, onUnload: function() { // 页面销毁时执行 }, onPullDownRefresh: function() { // 触发下拉刷新时执行 // 需要在app.json的window选项中或页面配置中开启enablePullDownRefresh }, onReachBottom: function() { // 页面触底时执行 // 可以在app.json的window选项中或页面配置中设置触发距离onReachBottomDistance。 // 在触发距离内滑动期间,本事件只会被触发一次。 }, onShareAppMessage: function () { //监听用户点击页面内转发按钮(button 组件 open-type="share")或右上角菜单“转发”按钮的行为,并自定义转发内容。 // 只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮 }, onPageScroll: function() { // 页面滚动时执行 // 只在需要的时候才在 page 中定义此方法,不要定义空方法。减少不必要的事件派发对渲染层-逻辑层通信的影响。 // 避免在 onPageScroll 中过于频繁的执行 setData 等引起逻辑层-渲染层通信的操作。 // 尤其是每次传输大量数据,会影响通信耗时。 }, 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' }})
onShareAppMessage(Object object)
监听用户点击页面内转发按钮(button 组件 open-type="share"
)或右上角菜单“转发”按钮的行为,并自定义转发内容。
注意:只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮
参数 Object object:
(1) from 转发事件来源。button
:页面内转发按钮;menu
:右上角转发菜单
(2) target 如果 from 值是 button,则 target 是触发这次转发事件的 button,否则为 undefined
(3) webViewUrl 页面中包含web-view组件时,返回当前web-view的url
此事件处理函数需要 return 一个 Object,用于自定义转发内容,返回内容如下:
(1) title 转发标题 ,默认是当前小程序名称
(2) path 转发路径 ,当前页面 path ,必须是以 / 开头的完整路径
(3) imageUrl 自定义图片路径,可以是本地文件路径、代码包文件路径或者网络图片路径。支持PNG及JPG。显示图片长宽比是 5:4。
Page({ onShareAppMessage: function (res) { if (res.from === 'button') { // 来自页面内转发按钮 console.log(res.target) } return { title: '自定义转发标题', path: '/page/user?id=123' } }})
onShareTimeline()
监听右上角菜单“分享到朋友圈”按钮的行为,并自定义分享内容。
注意:只有定义了此事件处理函数,右上角菜单才会显示“分享到朋友圈”按钮
事件处理函数返回一个 Object,用于自定义分享内容,不支持自定义页面路径,返回内容如下:
onTabItemTap(Object object)
点击 tab 时触发
Object 参数说明:
Page({ onTabItemTap(item) { console.log(item.index) console.log(item.pagePath) console.log(item.text) }})
Page 中还可以定义组件事件处理函数。在渲染层的组件中加入事件绑定,当事件被触发时,就会执行 Page 中定义的事件处理函数。
<view bindtap="viewTap"> click me view>
Page({ viewTap: function() { console.log('view tap') }})
Page.route 获取当前页面的路径
Page({ onShow: function() { console.log(this.route) }})
Page.prototype.setData(Object data, Function callback)
setData
函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data
的值(同步)
参数data 以Object形式传入,将data中的value值更新到this.data中。直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致。
不要把 data 中任何一项的 value 设为 undefined。
页面间通信
如果一个页面由另一个页面通过 wx.navigateTo
打开,这两个页面间将建立一条数据通道:
被打开的页面可以通过
this.getOpenerEventChannel()
方法来获得一个EventChannel
对象;wx.navigateTo
的success
回调中也包含一个EventChannel
对象。
这两个 EventChannel
对象间可以使用 emit
和 on
方法相互发送、监听事件。
(2)使用 Component 构造器构造页面
Page 构造器适用于简单的页面。但对于复杂的页面, Page 构造器可能并不好用。
可以使用 Component 构造器来构造页面。Component 构造器的主要区别是:方法需要放在 methods: { } 里面。
使用 Component 构造器来构造页面的一个好处是可以使用 behaviors 来提取所有页面中公用的代码段。
例如,在所有页面被创建和销毁时都要执行同一段代码,就可以把这段代码提取到 behaviors 中。
Component 构造器可用于定义组件,调用 Component 构造器时可以指定组件的属性、数据、方法等。
Component(Object object)
参数object中的属性包含:
properties---Object /Map 组件的对外属性,是属性名到属性设置的映射表
data---Objec 组件的内部数据
observers---Object 组件数据字段监听器,用于监听 properties 和 data 的变化
methods---Object 组件的方法,包括事件响应函数和任意的自定义方法
behaviors---String /Array 组件间代码复用机制
created---Function 生命周期函数-在组件实例刚刚被创建时执行
attached---Function 生命周期函数-在组件实例进入页面节点树时执行
ready---Function 生命周期函数-在组件布局完成后执行
moved---Function 生命周期函数-在组件实例被移动到节点树另一个位置时执行
detached---Function 生命周期函数-在组件实例被从页面节点树移除时执行
relations---Object 组件间关系定义
externalClasses---String /Array 组件接受的外部样式类
lifetimes---Object 声明组件生命周期
pageLifetimes---Object 声明组件所在页面的生命周期
Component({ behaviors: [], // 属性定义 properties: { myProperty: { // 属性名 type: String, value: '' }, myProperty2: { type: Number, value: 0, observer: function(newVal, oldVal) { // 属性值变化时执行,属性值的改变情况可以使用 observer 来监听 } } }, data: {}, // 私有数据,可用于模板渲染 lifetimes: { // 生命周期函数,可以为函数,或一个在methods段中定义的方法名 attached: function () { }, moved: function () { }, detached: function () { }, }, // 生命周期函数,可以为函数,或一个在methods段中定义的方法名 attached: function () { }, // 此处attached的声明会被lifetimes字段中的声明覆盖 ready: function() { }, pageLifetimes: { // 组件所在页面的生命周期函数 show: function () { }, hide: function () { }, resize: function () { }, }, methods: { onMyButtonTap: function(){ this.setData({ // 更新属性和数据的方法与更新页面数据的方法类似 }) }, // 内部方法建议以下划线开头 _myPrivateMethod: function(){ // 这里将 data.A[0].B 设为 'myPrivateData' this.setData({ 'A[0].B': 'myPrivateData' }) }, _propertyChange: function(newVal, oldVal) { } }})
在新版本基础库中不推荐使用observer来监听属性值变化,而是使用 Component 构造器的 observers 字段代替,它更加强大且性能更好。
数据监听器可以用于监听和响应任何属性和数据字段的变化,可以同时监听多个,并且可以监听子数据字段。
Component({ observers: { 'some.subfield': function(subfield) { // 使用 setData 设置 this.data.some.subfield 时触发 // (除此以外,使用 setData 设置 this.data.some 也会触发) subfield === this.data.some.subfield }, 'arr[12]': function(arr12) { // 使用 setData 设置 this.data.arr[12] 时触发 // (除此以外,使用 setData 设置 this.data.arr 也会触发) arr12 === this.data.arr[12] }, }})
如果需要监听所有子数据字段的变化,可以使用通配符 **
Component({ observers: { 'some.field.**': function(field) { // 使用 setData 设置 this.data.some.field 本身或其下任何子数据字段时触发 // (除此以外,使用 setData 设置 this.data.some 也会触发) field === this.data.some.field }, }, attached: function() { // 这样会触发上面的 observer this.setData({ 'some.field': { /* ... */ } }) // 这样也会触发上面的 observer this.setData({ 'some.field.xxx': { /* ... */ } }) // 这样还是会触发上面的 observer this.setData({ 'some': { /* ... */ } }) }})
如果仅使用通配符 **
可以监听全部 setData
Component({ observers: { '**': function() { // 每次 setData 都触发 }, },})
数据监听器监听的是 setData 涉及到的数据字段,即使这些数据字段的值没有发生变化,数据监听器依然会被触发。
如果在数据监听器函数中使用 setData 设置本身监听的数据字段,可能会导致死循环,需要特别留意。