Page
對象小程序是經過調用 Page
函數來註冊一個頁面的:vue
//index.js
Page({
data: {
text: "This is page data."
},
onLoad: function(options) {
// Do some initialize when page load.
},
// Event handler.
viewTap: function() {
this.setData({
text: 'Set some data for updating view.'
}, function() {
// this is setData callback
})
}
})
複製代碼
這裏Page
的做用至關於構造函數,Page
會初始化頁面對象(實例),而後將配置參數中的屬性 merge 到頁面對象上。ios
假設你封裝了個http
模塊負責發出請求,你想在頁面對象中直接經過this.http
引用這個模塊,就須要擴展頁面對象。要擴展一個對象,在 JavaScript 中的常見作法是擴展構造函數的prototype
屬性,這是Vue
不少插件的實現:npm
import axios from 'axios'
Vue.prototype.axios = axios
// 在 vue 組件中
this.axios.get(api).then(callback)
複製代碼
很不幸,在小程序中這個辦法無效。Page
並非普通的構造函數,底層還作了不少其餘事情,沒辦法直接經過Page.prototype
擴展頁面對象。axios
咱們能夠轉變思路,擴展傳進Page
的配置對象。既然始終要經過調用Page
註冊頁面,能夠定義一個函數,這個函數會將收到的配置對象參數進行處理,而後再傳給Page
。小程序
// wxPage.js
import http from '../utils/http'
const wxPage = function(config) {
config.http = http
return Page(config)
}
export default wxPage
複製代碼
註冊頁面的時候改用這個wxPage
:api
import Page from './wxPage'
Page({
data: {
text: "This is page data."
},
onLoad: function(options) {
console.log(this.http) // 打印 http 模塊變量
this.http.get(api).then(callback) // 直接調用 http 的方法
},
})
複製代碼
Page
函數爲了加強頁面對象,每一個須要的頁面都得引入 wxPage
是一件不太省心的事;更多時候咱們是在維護一個老項目,須要擴展每一個原有的頁面對象,這時能夠直接修改 Page
:bash
const originalPage = Page //保存原來的Page
Page = function(config) { // 覆蓋Page變量
config.http = http
return originalPage(config)
}
複製代碼
通常來講,修改 Page
的時機是在App
onLoad
的時候。這樣原有的頁面不用修改,直接就能經過this.http
拿到http
。函數
Page
頁面對象實現常見需求有時咱們但願在頁面註冊的onLoad
階段執行一些通用的邏輯,例如埋點,打 log 等,這時能夠改寫配置對象中的 onLoad
方法:ui
const originalPage = Page
Page = function(config) {
const { onLoad } = config
config.onLoad = function(onLoadOptions) {
// 打 log、埋點……
console.log('每一個頁面都會打出這個log')
if (typeof onLoad === 'function') {
onLoad.call(this, onLoadOptions)
}
}
return originalPage(config)
}
複製代碼
小程序中的頁面跳轉會造成一個頁面棧,棧中存放着每一個頁面對象,能夠經過 getCurrentPages
方法得到這個頁面棧。能夠在頁面 onLoad
的時候獲取這個頁面棧,而後取出倒數第二個對象,就是當前頁上一頁的頁面對象:this
// 接上...
const { onLoad } = config
config.onLoad = function(onLoadOptions) {
const pages = getCurrentPages()
this.__previousPage = pages[pages.length - 2] // 將上一頁的頁面對象賦爲this.__previousPage
if (typeof onLoad === 'function') {
onLoad.call(this, onLoadOptions)
}
}
return originalPage(config)
複製代碼
這樣在頁面對象中可經過引用 this.__previousPage
獲取上一頁頁面對象的data及全部方法,這樣在一些只須要兩個頁面互動的情景下,當前頁直接調用上一個頁面對象的方法(至關於回調)後再返回,比經過全局狀態管理上一頁的數據要方便。
這個很少說了,直接看代碼吧:
// 接上
config.navigateTo = function(url, params) { // 實現一個navigateTo方法,參數包括跳轉url和要傳遞的參數
this.__params = params
wx.navigateTo({ url })
}
config.onLoad = function(onLoadOptions) {
const pages = getCurrentPages()
this.__previousPage = pages[pages.length - 2] // 將上一頁的頁面對象賦爲this.__previousPage
if (this.__previousPage) {
onLoadOptions.params = this.__previousPage.__params // 獲取上一頁面的__params賦給onLoad函數的options
delete this.__previousPage.__params
}
if (typeof onLoad === 'function') {
onLoad.call(this, onLoadOptions)
}
}
// A 頁面跳轉 B 頁面
this.navigateTo('urlToB', { foo: 'bar' })
// B 頁面的 onLoad
Page({
onLoad(options) {
console.log(options.params) // { foo: 'bar' }
}
})
複製代碼
就寫到這裏吧,在使用原生方案開發的時候,這些技巧仍是挺實用的。之後再寫寫怎樣構建小程序,使小程序支持文件預編譯、require npm 包等。