微信小程式開發《6 .框架之邏輯層》
場景值
基礎庫 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 | 公眾號自定義選單 |
1036 | App 分享訊息卡片 |
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 | 城市服務入口 |
可以在 App 的 onlaunch 和 onshow 中獲取上述場景值,部分場景值下還可以獲取來源應用、公眾號或小程式的appId。詳見
Tip: 由於Android系統限制,目前還無法獲取到按 Home 鍵退出到桌面,然後從桌面再次進小程式的場景值,對於這種情況,會保留上一次的場景值。
註冊頁面Page
Page()
函式用來註冊一個頁面。接受一個 object 引數,其指定頁面的初始資料、生命週期函式、事件處理函式等。
object 引數說明:
屬性 | 型別 | 描述 |
---|---|---|
data | Object | 頁面的初始資料 |
onLoad | Function | 生命週期函式--監聽頁面載入 |
onReady | Function | 生命週期函式--監聽頁面初次渲染完成 |
onShow | Function | 生命週期函式--監聽頁面顯示 |
onHide | Function | 生命週期函式--監聽頁面隱藏 |
onUnload | Function | 生命週期函式--監聽頁面解除安裝 |
onPullDownRefresh | Function | 頁面相關事件處理函式--監聽使用者下拉動作 |
onReachBottom | Function | 頁面上拉觸底事件的處理函式 |
onShareAppMessage | Function | 使用者點選右上角轉發 |
onPageScroll | Function | 頁面滾動觸發事件的處理函式 |
onTabItemTap | Function | 當前是 tab 頁時,點選 tab 時觸發 |
其他 | Any | 開發者可以新增任意的函式或資料到 object 引數中,在頁面的函式中用 this 可以訪問 |
object 內容在頁面載入時會進行一次深拷貝,需考慮資料大小對頁面載入的開銷
示例程式碼:
//index.js
Page({
data: {
text: "This is page data."
},
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)
},
// Event handler.
viewTap: function() {
this.setData({
text: 'Set some data for updating view.'
}, function() {
// this is setData callback
})
},
customData: {
hi: 'MINA'
}
})
初始化資料
初始化資料將作為頁面的第一次渲染。data 將會以 JSON 的形式由邏輯層傳至渲染層,所以其資料必須是可以轉成 JSON 的格式:字串,數字,布林值,物件,陣列。
渲染層可以通過 WXML 對資料進行繫結。
示例程式碼:
<view>{{text}}</view>
<view>{{array[0].msg}}</view>
Page({
data: {
text: 'init data',
array: [{msg: '1'}, {msg: '2'}]
}
})
生命週期函式
onLoad
: 頁面載入- 一個頁面只會呼叫一次,可以在 onLoad 中獲取開啟當前頁面所呼叫的 query 引數。
onShow
: 頁面顯示- 每次開啟頁面都會呼叫一次。
onReady
: 頁面初次渲染完成- 一個頁面只會呼叫一次,代表頁面已經準備妥當,可以和檢視層進行互動。
- 對介面的設定如
wx.setNavigationBarTitle
請在onReady
之後設定。
onHide
: 頁面隱藏- 當
navigateTo
或底部tab
切換時呼叫。
- 當
onUnload
: 頁面解除安裝- 當
redirectTo
或navigateBack
的時候呼叫。
- 當
onLoad引數
型別 | 說明 |
---|---|
Object | 其他頁面開啟當前頁面所呼叫的 query 引數 |
頁面相關事件處理函式
onPullDownRefresh
: 下拉重新整理onReachBottom
: 上拉觸底onPageScroll
: 頁面滾動- 監聽使用者滑動頁面事件。
- 引數為 Object,包含以下欄位:
欄位 | 型別 | 說明 |
---|---|---|
scrollTop | Number | 頁面在垂直方向已滾動的距離(單位px) |
onShareAppMessage
: 使用者轉發- 只有定義了此事件處理函式,右上角選單才會顯示“轉發”按鈕
- 使用者點選轉發按鈕的時候會呼叫
- 此事件需要 return 一個 Object,用於自定義轉發內容
自定義轉發欄位
欄位 | 說明 | 預設值 |
---|---|---|
title | 轉發標題 | 當前小程式名稱 |
path | 轉發路徑 | 當前頁面 path ,必須是以 / 開頭的完整路徑 |
示例程式碼
Page({
onShareAppMessage: function () {
return {
title: '自定義轉發標題',
path: '/page/user?id=123'
}
}
})
事件處理函式
除了初始化資料和生命週期函式,Page 中還可以定義一些特殊的函式:事件處理函式。在渲染層可以在元件中加入事件繫結,當達到觸發事件時,就會執行 Page 中定義的事件處理函式。
示例程式碼:
<view bindtap="viewTap"> click me </view>
Page({
viewTap: function() {
console.log('view tap')
}
})
Page.prototype.route
route
欄位可以獲取到當前頁面的路徑。
Page.prototype.setData()
setData
函式用於將資料從邏輯層傳送到檢視層(非同步),同時改變對應的 this.data
的值(同步)。
setData() 引數格式
欄位 | 型別 | 必填 | 描述 | 最低版本 |
---|---|---|---|---|
data | Object | 是 | 這次要改變的資料 | |
callback | Function | 否 | 回撥函式 | 1.5.0 |
object 以 key,value 的形式表示將 this.data 中的 key 對應的值改變成 value。 callback 是一個回撥函式,在這次setData對介面渲染完畢後呼叫。
其中 key 可以非常靈活,以資料路徑的形式給出,如 array[2].message
,a.b.c.d
,並且不需要在 this.data 中預先定義。
注意:
- 直接修改 this.data 而不呼叫 this.setData 是無法改變頁面的狀態的,還會造成資料不一致。
- 單次設定的資料不能超過1024kB,請儘量避免一次設定過多的資料。
- 請不要把 data 中任何一項的 value 設為
undefined
,否則這一項將不被設定並可能遺留一些潛在問題。
示例程式碼:
<!--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>
//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'
})
}
})
生命週期
下圖說明了 Page 例項的生命週期。
頁面路由
頁面棧
框架以棧的形式維護了當前的所有頁面。 當發生路由切換的時候,頁面棧的表現如下:
路由方式 | 頁面棧表現 |
---|---|
初始化 | 新頁面入棧 |
開啟新頁面 | 新頁面入棧 |
頁面重定向 | 當前頁面出棧,新頁面入棧 |
頁面返回 | 頁面不斷出棧,直到目標返回頁,新頁面入棧 |
Tab 切換 | 頁面全部出棧,只留下新的 Tab 頁面 |
重載入 | 頁面全部出棧,只留下新的頁面 |
getCurrentPages()
getCurrentPages()
函式用於獲取當前頁面棧的例項,以陣列形式按棧的順序給出,第一個元素為首頁,最後一個元素為當前頁面。
Tip:不要嘗試修改頁面棧,會導致路由以及頁面狀態錯誤。
路由方式
對於路由的觸發方式以及頁面生命週期函式如下:
Tab 切換對應的生命週期(以 A、B 頁面為 Tabbar 頁面,C 是從 A 頁面開啟的頁面,D 頁面是從 C 頁面開啟的頁面為例):
當前頁面 | 路由後頁面 | 觸發的生命週期(按順序) |
---|---|---|
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() |
D | 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() |
Tips:
navigateTo
,redirectTo
只能開啟非 tabBar 頁面。switchTab
只能開啟 tabBar 頁面。reLaunch
可以開啟任意頁面。- 頁面底部的 tabBar 由頁面決定,即只要是定義為 tabBar 的頁面,底部都有 tabBar。
- 呼叫頁面路由帶的引數可以在目標頁面的
onLoad
中獲取。
檔案作用域
在 JavaScript 檔案中宣告的變數和函式只在該檔案中有效;不同的檔案中可以宣告相同名字的變數和函式,不會互相影響。
通過全域性函式 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)
模組化
可以將一些公共的程式碼抽離成為一個單獨的 js 檔案,作為一個模組。模組只有通過 module.exports
或者 exports
才能對外暴露介面。
需要注意的是:
exports
是module.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
tip
: require 暫時不支援絕對路徑