小程序开发实用技巧——扩展 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 包等。

相关文章
相关标签/搜索