小程序開發實用技巧——擴展 Page 頁面對象

擴展原生 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
複製代碼

註冊頁面的時候改用這個wxPageapi

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 是一件不太省心的事;更多時候咱們是在維護一個老項目,須要擴展每一個原有的頁面對象,這時能夠直接修改 Pagebash

const originalPage = Page //保存原來的Page
Page = function(config) { // 覆蓋Page變量
  config.http = http
  return originalPage(config)
}
複製代碼

通常來講,修改 Page 的時機是在App onLoad 的時候。這樣原有的頁面不用修改,直接就能經過this.http拿到http函數

經過擴展 Page 頁面對象實現常見需求

1. 給生命週期方法增長通用邏輯

有時咱們但願在頁面註冊的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)
}
複製代碼

2. 獲取上一頁頁面對象

小程序中的頁面跳轉會造成一個頁面棧,棧中存放着每一個頁面對象,能夠經過 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及全部方法,這樣在一些只須要兩個頁面互動的情景下,當前頁直接調用上一個頁面對象的方法(至關於回調)後再返回,比經過全局狀態管理上一頁的數據要方便。

3. 跳轉頁面並傳遞數據到下一頁

這個很少說了,直接看代碼吧:

// 接上
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 包等。

相關文章
相關標籤/搜索