您好,登錄后才能下訂單哦!
問題
在之前開發微信小程序的時候,獲取用戶信息、openid還有地理位置這些信息的時候,都是采用Promise的方式異步獲取,但是這樣的話在頁面和App.js中都獲取就可能造成請求重復的問題。
比如為了在每個頁面都能獲取到這些共享信息,都會選擇在App.js中進行獲取,然后在頁面級進行獲取,這兩次獲取的時間間隔較小時就可能導致前一個請求還未獲取到數據,后一個請求就會再次進行獲取,這樣就產生了兩次請求。
還有一個問題就是書寫麻煩(雖然也能通過async await簡化),比如
onLoad() { app.getUserInfo() .then(userInfo => { }).catch(err => { /* 錯誤處理 */ }); // 如果同時需要userInfo和openid,可能就是如下形式: Promise.all([app.getUserInfo(), app.getOpenid()]) .then(res => { }).catch(err => { /* 錯誤處理 */ }); }
正好周末的時候突然想到了vue的watch語法,利用一些相關的知識,就可以解決這個麻煩的問題了。
解決思路
雙向綁定
vue的雙向綁定原理,3.0將會采用Proxy監聽數據變化,不過考慮到小程序這邊的Proxy兼容性我不知道,所以采用了2.0的Object.defineProperty
來監聽數據的變化。
主要還是攔截設置的操作,在進行賦值時,將新舊值通知至監聽者。
觀察者模式
在頁面級的onLoad監聽app.globalData
各個鍵名的事件,而在app.js的onLoad中則使用Object.defineProperty
重新定義app.globalData
,這樣一旦app.globalData
相應的鍵值發生了變化,就會通知監聽的頁面該值發生了變化。
模塊化的引用
觀察者模式導出的是一個對象(類實例),而不是一個類,所以在導入的時候這個對象是共享的,就可以通過這個對象將app.js和其他頁面聯系起來。
至于模塊加載的實質,ES6模塊加載的機制,與CommonJS模塊完全不同。感興趣的可以去看看這個。
封裝Page
小程序的Page函數本身是不支持watch,但是我們可以自定義一個函數,進行參數合并就可以了。
在頁面onLoad時先遍歷watch屬性,對app.globalData
進行監聽,可以參考vue的watch用法。
頁面onUnload時就會進行銷毀,此時也應該取消監聽,這些我都封裝過了,不用手動處理了。
有了這些思路,用不了多久,一個雛形就出來了,經過手動測試,感覺沒什么問題,我就發布到npm了,大家感興趣的可以安裝體驗一下。
安裝
npm i wx-watch -S --production
使用
// app.js var { watchData, } = require('/miniprogram_npm/wx-watch/index.js'); App({ onLaunch() { this.watchData(); /* 監聽this.globalData的變化,并觸發事件,其他頁面監聽的值必須在globalData中預先定義,否則無法監聽 */ }, watchData, globalData: { userInfo: null, } }); // 其他需要監聽globalData的頁面.js var { getPage } = require('../../miniprogram_npm/wx-watch/index.js'); const app = getApp(); /** * getPage(頁面參數,app) app必傳,因為封裝的時候訪問不到,就只能傳參了 */ getPage({ watch: { userInfo(userInfo, oldUserInfo) { console.log(`來自app.glodalData的userInfo`); } }, // 其他參數 }, app)
github: github.com/ma125120/wx…
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。