去年年末,微信小程式的分包大小已經到達了12M 大小,一方面說明小程式的確逐步為開發者放開更大的權限,另一方面也說明了對於某些小程式8M的大小已經不夠用了。我個人今年也是在開發 to B 小程式應用程式。這裡列舉一些跨頁面互動的場景。
對於 B 端應用程式的業務需求來說,小程式開發的複雜度相對比網頁開發複雜一些。一個是雙執行緒的處理機制問題,另一個是頁面棧之間互動問題。
註: 筆者目前只需要開發微信小程序,為了在小程式頁面中可以使用 properties behaviors observers 等新功能,已經使用 Component 建構器來建構頁面。具體可以參考微信小程式 Component 建構器。如果你也沒有多端開發的需求,建議嘗試使用,可以得到不錯的體驗。
效能最佳化類別
對於小程式在頁面中點擊觸發wx.navigateTo 跳轉其他頁面,中間會有一段時間的空白加載期(對於分包出去的頁面,空白期則會更長),但是這是小程式內部機制,沒有辦法進行優化。我們只能眼睜睜的等待這段沒有意思的空白期過去。
當考慮到跳轉頁面後的第一件事情便是取數邏輯,那麼我們是否能夠進行最佳化呢?答案是肯定的。我們沒有辦法直接在當前頁面取得資料之後再進行跳轉操作(這樣操作更不好),但是我們卻可以利用快取當前的請求,詳情可以參考我之前的部落格文章 ——Promise物件 3 種妙用。
程式碼如下:
const promiseCache = new Map() export function setCachePromise(key, promise) { promiseCache.set(key, promise) } export function getCachePromise(key) { // 根据key获取当前的数据 const promise = promiseCache.get(key) // 用完删除,目前只做中转用途,也可以添加其他用途 promiseCache.delete(key) return promise }
做一份全域的Map,然後利用Map 快取promise 對象,在跳轉之前程式碼為:
// 导入 setCachePromise 函数 Component({ methods: { getBookData(id) { const promise = // promise 请求 setCachePromise(`xxx:${id}`, promise) }, handleBookDetailShow(e) { const id = e.detail this.getBookData(id) wx.navigateTo({url: `xx/xx/x?id=${id}`}) } } })
而跳轉之後的程式碼也如下所示:
// 导入 getCachePromise 函数 Component({ properties: { id: Number }, lifetimes: { attached () { const id = this.data.id // 取得全局缓存的promise const bookPromise = getCachePromise(`xxx:${id}`) bookPromise.then((res) => { // 业务处理 }).catch(error => { // 错误处理 }) } }, methods: { getBook() { // 获取数据,以便于 错误处理 上拉刷新 等操作 } } })
如此便可以同時處理取數和頁面載入的邏輯,當然,這個對於頁面有耦合性,不利於後續的刪除與修改。但考慮如果僅加在分包跳轉之間可能會有不錯的效果。
想要無侵入式,可以進一步學習研究 微信小程式之提高應用速度小技巧 以及 wxpage 框架,同時考慮到無論是ToC 還是ToC 用戶,都有可能存在硬體以及網路環境等問題,該優化還是非常值得的。
當然微信小程式為了減少冷啟動時間,提供了週期性更新 資料預拉取 功能。
註: 上面的 promiseCache 只作為中轉的用途,不作為緩存的用途,如果你考慮添加緩存,可以參考我之前的博客文章—— 前端 api 請求緩存方案。
通知類
如果是 pc 端中進行交互,對於資料的 CRUD。例如在詳情頁面進行了資料的修改和刪除,返回清單時候就直接調取先前儲存的清單查詢條件再次查詢即可,而對於行動端這種下拉滾動的設計,就沒有辦法直接呼叫先前的查詢條件來進行搜尋。
如果從清單頁面進入詳情頁面後,在詳情頁面只會進行新增或修改操作。然後返回列表頁面。此時可以提示使用者資料已經進行了修改,請使用者自行決定是否進行刷新操作。
如在編輯頁面修改了資料:
const app = getApp() component({ methods: { async handleSave() { //... app.globalData.xxxChanged = true //... } } })
清單介面:
const app = getApp() component({ pageLifetimes: { show() { this.confirmThenRefresh() } }, methods: { confirmThenRefresh() { // 检查 globalData,如果当前没有进行修改,直接返回 if(!app.globalData.xxxChanged) return wx.showModal({ // ... complete: () => { // 无论确认刷新与否,都把数据置为 false app.globalData.xxxChanged = false } }) } } })
當然了,我們也可以利用wx.setStorage 或getCurrentPage 來取得前面的頁面setData 來進行資料通知,以便使用者進行頁面重新整理。
訂閱發布類別
如果僅只涉及到修改資料的前提下,我們可以選擇讓使用者進行刷新操作,但是如果針對於刪除操作而言,如果用戶選擇不進行刷新,然後用戶又不小心點擊到了已經刪除的數據,就會發生錯誤。所以如果有刪除的需求,我們最好在返回清單頁面前就進行清單的修改,以免造成錯誤。
mitt
github 上有很多的pub/sub 開源函式庫,如果沒有特定的需求,找到程式碼量最少的就是 mitt這個庫了,作者是喜歡開發微型庫的 developit 大佬,著名的 preact 也是出於這位大佬之手。這裡就不做過多的介紹,非常簡單。大家可能都能看明白,程式碼如下(除去 flow 工具的檢查):
export default function mitt(all) { all = all || Object.create(null); return { on(type, handler) { (all[type] || (all[type] = [])).push(handler); }, off(type, handler) { if (all[type]) { all[type].splice(all[type].indexOf(handler) >>> 0, 1); } }, emit(type, evt) { (all[type] || []).slice().map((handler) => { handler(evt); }); (all['*'] || []).slice().map((handler) => { handler(type, evt); }); } }; }
僅僅只有3個方法,on emit以及 off。
只要在多個頁面匯入 產生的 mitt() 函數產生的物件即可(或直接放入 app.globalData 中也可)。
Component({ lifetimes: { attached: function() { // 页面创建时执行 const changeData = (type, data) => { // 处理传递过来的类型与数据 } this._changed = changeData bus.on('xxxchanged', this._changed) }, detached: function() { // 页面销毁时执行 bus.off('xxxchanged', this._changed) } } })
这里mitt
可以有多个页面进行绑定事件,如果需求仅仅只涉及到两个页面之间,我们就可以使用 wx.navigateTo
中的 EventChannel
(页面间事件信息通道)。可以参考微信小程序wx.navigateTo
方法里的events
参数使用详情及场景,该方案的利好在于,传递到下一个页面的参数也可以通过 EventChannel
来通知,以便于解决 properties 传递数据不宜过大的问题。
注: 一个页面展示很多信息的时候,会造成小程序页面的卡顿以及白屏。小程序官方也有长列表组件 recycle-view
。有需求的情况下可以自行研究,这个不在这里详述。
鼓励一下
如果你觉得这篇文章不错,希望可以给与我一些鼓励,在我的 github 博客下帮忙 star
一下。
博客地址
推荐教程:《微信小程序》
以上是小程式跨頁面互動的作用和方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!