Практические советы по разработке мини-программы - расширение объекта страницы

JavaScript Апплет WeChat

Расширение нативногоPageобъект

Апплет вызываетсяPageфункция для регистрации страницы:

//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Объект страницы (экземпляр) инициализируется, а затем свойства в параметрах конфигурации объединяются с объектом страницы.

Предположим, вы инкапсулируетеhttpМодуль отвечает за выполнение запроса, вы хотите передать его прямо в объекте страницыthis.httpЧтобы сослаться на этот модуль, вам необходимо расширить объект страницы. Чтобы расширить объект, в JavaScript обычной практикой является расширение конструктора.prototypeсобственность, котораяVueРеализация многих плагинов:

import axios from 'axios'
Vue.prototype.axios = axios
// 在 vue 组件中
this.axios.get(api).then(callback)

К сожалению, этот подход не работает в апплете.PageЭто не обычный конструктор, нижний слой также делает много других вещей, нет возможности передать его напрямуюPage.prototypeРасширяет объект страницы.

Мы можем изменить наше мышление и расширитьPageобъект конфигурации. Так как всегда нужно звонитьPageНа странице регистрации вы можете определить функцию, которая будет обрабатывать полученные параметры объекта конфигурации, а затем передавать их вPage.

// wxPage.js
import http from '../utils/http'

const wxPage = function(config) {
  config.http = http
  return Page(config)
}

export default wxPage

Используйте это вместо этого при регистрации страницыwxPage:

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:

const originalPage = Page //保存原来的Page
Page = function(config) { // 覆盖Page变量
  config.http = http
  return originalPage(config)
}

В общем модифицироватьPageвремя вApp onLoadкогда. Таким образом, исходная страница может быть передана напрямую без изменений.this.httpполучатьhttp.

по расширениюPageОбъекты страницы реализуют общие требования

1. Добавьте общую логику к методам жизненного цикла

Иногда мы хотим зарегистрироваться на страницеonLoadСтадия выполняет некоторую общую логику, такую ​​как закапывание точек, логирование и т. д. В это время вы можете переписать объект конфигурацииonLoadметод:

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Когда стек страниц получен, то вынимается предпоследний объект, который является объектом страницы предыдущей страницы текущей страницы:

// 接上...
  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Получите данные и все методы объекта страницы на предыдущей странице, чтобы в некоторых сценариях, где для взаимодействия требуется только две страницы, текущая страница напрямую вызывала метод объекта предыдущей страницы (эквивалентно обратному вызову), а затем возвращала , что лучше, чем управление глобальным состоянием. Одна страница данных должна быть удобной.

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' }
  }
})

Просто напишите сюда, эти навыки весьма практичны при разработке с нативными решениями. Позже я напишу о том, как собрать апплет, чтобы апплет поддерживал предкомпиляцию файлов, требовал npm-пакет и т.д.