摘要:另外因為依賴,而可能出現讀寫失敗,從面造成通信失敗注意點頁面初始化時也會觸發方式二小程序同方式一一樣,利用激活方法,通過讀寫小程序完成數據傳遞清隊上次通信數據優點實現簡單,實現理解。
微信小程序頁面間通的5種方式
PageModel(頁面模型)對小程序而言是很重要的一個概念,從app.json中也可以看到,小程序就是由一個個頁面組成的。
如上圖,這是一個常見結構的小程序:首頁是一個雙Tab框架PageA和PageB,子頁面pageB, PageC。
讓我們假設這樣一個場景:首頁PageA有一個飄數,當我們從PageA新開PageC后,做一些操作,再回退到PageA的時候,這個飄數要刷新。很顯然,這需要在PageC中做操作時,能通知到PageA,以便PageA做相應的聯動變化。
這里的通知,專業點說就是頁面通信。所謂通信,u3認為要滿足下面兩個條件:
激活對方的一個方法調用
能夠向被激活的方法傳遞數據
本文將根據項目實踐,結合小程序自身特點,就小程序頁面間通信方式作一個探討與小結。
通信分類按頁面層級(或展示路徑)可以分為:
兄弟頁面間通信。如多Tab頁面間通信,PageA,PageB之間通信
父路徑頁面向子路徑頁面通信,如PageA向PageC通信
子路徑頁面向父路徑頁面通信,如PageC向PageA通信
按通信時激活對方方法時機,又可以分為:
延遲激活,即我在PageC做完操作,等返回到PageA再激活PageA的方法調用
立即激活,即我在PageC做完操作,在PageC激活PageA的方法調用
方式一:onShow/onHide + localStorage利用onShow/onHide激活方法,通過localStorage傳遞數據。大概邏輯如下
// pageA let isInitSelfShow = true; Page({ data: { helloMsg: "hello from PageA" }, onShow() { // 頁面初始化也會觸發onShow,這種情況可能不需要檢查通信 if (isInitSelfShow) return; let newHello = wx.getStorageSync("__data"); if (newHello) { this.setData({ helloMsg: newHello }); // 清隊上次通信數據 wx.clearStorageSync("__data"); } }, onHide() { isInitSelfShow = false; }, goC() { wx.navigateTo({ url: "/pages/c/c" }); } });
// pageC Page({ doSomething() { wx.setStorageSync("__data", "hello from PageC"); } });
優點:實現簡單,容易理解
缺點:如果完成通信后,沒有即時清除通信數據,可能會出現問題。另外因為依賴localStorage,而localStorage可能出現讀寫失敗,從面造成通信失敗
注意點:頁面初始化時也會觸發onShow
同方式一一樣,利用onShow/onHide激活方法,通過讀寫小程序globalData完成數據傳遞
// PageA let isInitSelfShow = true; let app = getApp(); Page({ data: { helloMsg: "hello from PageA" }, onShow() { if (isInitSelfShow) return; let newHello = app.$$data.helloMsg; if (newHello) { this.setData({ helloMsg: newHello }); // 清隊上次通信數據 app.$$data.helloMsg = null; } }, onHide() { isInitSelfShow = false; }, goC() { wx.navigateTo({ url: "/pages/c/c" }); } });
// PageC let app = getApp(); Page({ doSomething() { app.$$data.helloMsg = "hello from pageC"; } });
優點:實現簡單,實現理解。因為不讀寫localStorage,直接操作內存,所以相比方式1,速度更快,更可靠
缺點:同方式1一樣,要注意globalData污染
這種方式要先實現一個PubSub,通過訂閱發布實現通信。在發布事件時,激活對方方法,同時傳入參數,執行事件的訂閱方法
/* /plugins/pubsub.js * 一個簡單的PubSub */ export default class PubSub { constructor() { this.PubSubCache = { $uid: 0 }; } on(type, handler) { let cache = this.PubSubCache[type] || (this.PubSubCache[type] = {}); handler.$uid = handler.$uid || this.PubSubCache.$uid++; cache[handler.$uid] = handler; } emit(type, ...param) { let cache = this.PubSubCache[type], key, tmp; if(!cache) return; for(key in cache) { tmp = cache[key]; cache[key].call(this, ...param); } } off(type, handler) { let counter = 0, $type, cache = this.PubSubCache[type]; if(handler == null) { if(!cache) return true; return !!this.PubSubCache[type] && (delete this.PubSubCache[type]); } else { !!this.PubSubCache[type] && (delete this.PubSubCache[type][handler.$uid]); } for($type in cache) { counter++; } return !counter && (delete this.PubSubCache[type]); } }
//pageA let app = getApp(); Page({ data: { helloMsg: "hello from PageA" }, onLoad() { app.pubSub.on("hello", (number) => { this.setData({ helloMsg: "hello times:" + number }); }); }, goC() { wx.navigateTo({ url: "/pages/c/c" }); } });
//pageC let app = getApp(); let counter = 0; Page({ doSomething() { app.pubSub.emit("hello", ++counter); }, off() { app.pubSub.off("hello"); } });
缺點:要非常注意重復綁定的問題
方式四:gloabelData watcher方式前面提到方式中,我們有利用globalData完成通信。現在數據綁定流行,結合redux單一store的思想,如果我們直接watch一個globalData,那么要通信,只需修改這個data值,通過water去激活調用。
同時修改的data值,本身就可以做為參數數據。
為了方便演示,這里使用oba這個開源庫做為對象監控庫,有興趣的話,可以自己實現一個。
//pageA import oba from "../../plugin/oba"; let app = getApp(); Page({ data: { helloMsg: "hello from PageA" }, onLoad() { oba(app.$$data, (prop, newvalue, oldValue) => { this.setData({ helloMsg: "hello times: " + [prop, newvalue, oldValue].join("#") }); }); }, goC() { wx.navigateTo({ url: "/pages/c/c" }); } });
//pageC let app = getApp(); let counter = 0; Page({ doSomething() { app.$$data.helloTimes = ++counter; } });
優點:數據驅動,單一數據源,便于調試
缺點:重復watch的問題還是存在,要想辦法避免
直接緩存頁面PageModel, 通信時,直接找到要通信頁面的PageModel,進而可以訪問通信頁面PageModel所有的屬性,方法。簡直不能太cool,感謝小組內小伙伴發現這么amazing的方式。
有人肯定會問了,怎么拿到這個所有的PageModel呢。其它很簡單,每個頁面有onLoad方法,我們在這個事件中,把this(即些頁面PageModel)緩存即可,緩存時用頁面路徑作key,方便查找。那么頁面路徑怎么獲取呢,答案就是page__route__這個屬性
// plugin/pages.js // 緩存pageModel,一個簡要實現 export default class PM { constructor() { this.$$cache = {}; } add(pageModel) { let pagePath = this._getPageModelPath(pageModel); this.$$cache[pagePath] = pageModel; } get(pagePath) { return this.$$cache[pagePath]; } delete(pageModel) { try { delete this.$$cache[this._getPageModelPath(pageModel)]; } catch (e) { } } _getPageModelPath(page) { // 關鍵點 return page.__route__; } }
// pageA let app = getApp(); Page({ data: { helloMsg: "hello from PageA" }, onLoad() { app.pages.add(this); }, goC() { wx.navigateTo({ url: "/pages/c/c" }); }, sayHello(msg) { this.setData({ helloMsg: msg }); } });
//pageC let app = getApp(); Page({ doSomething() { // 見證奇跡的時刻 app.pages.get("pages/a/a").sayHello("hello u3xyz.com"); } });
優點:一針見血,功能強大,可以向要通信頁面做你想做的任何事。無需要綁定,訂閱,所以也就不存在重復的情況
缺點:使用了__route__這個hack屬性,可能會有一些風險
以上!
原文地址: http://www.u3xyz.com/#/detail/20
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/82288.html
摘要:傳統的網頁編程采用的三劍客來實現,在微信小程序中同樣有三劍客。觀察者模式不難實現,重點是如何在微信小程序中搭配其特有的生命周期來使用。交互事件傳統的事件傳遞類型有冒泡型與捕獲型,微信小程序中自然也有。 本文由作者鄒永勝授權網易云社區發布。 簡介為了更好的展示我們即時通訊SDK強悍的能力,網易云信IM SDK微信小程序DEMO的開發就提上了日程。用產品的話說就是: 云信 IM 小程序 S...
摘要:與之間通過橋協議通信包括調用指令和各種事件,涉及消息序列化跨線程通信與。一個小程序可以有多個,頁面間切換動畫比更流暢。業務無法直接控制。 showImg(http://upload-images.jianshu.io/upload_images/326507-e81e06b2cb7187e9.jpeg?imageMogr2/auto-orient/strip%7CimageView2/...
摘要:相比之下,小程序的鉤子函數要簡單得多。一生命周期先貼兩張圖生命周期小程序生命周期相比之下,小程序的鉤子函數要簡單得多。的鉤子函數在跳轉新頁面時,鉤子函數都會觸發,但是小程序的鉤子函數,頁面不同的跳轉方式,觸發的鉤子并不一樣。 前言 寫了vue項目和小程序,發現二者有許多相同之處,在此想總結一下二者的共同點和區別。相比之下,小程序的鉤子函數要簡單得多。 寫了vue項目和小程序,發現二者有...
摘要:相比之下,小程序的鉤子函數要簡單得多。一生命周期先貼兩張圖生命周期小程序生命周期相比之下,小程序的鉤子函數要簡單得多。的鉤子函數在跳轉新頁面時,鉤子函數都會觸發,但是小程序的鉤子函數,頁面不同的跳轉方式,觸發的鉤子并不一樣。 前言 寫了vue項目和小程序,發現二者有許多相同之處,在此想總結一下二者的共同點和區別。相比之下,小程序的鉤子函數要簡單得多。 寫了vue項目和小程序,發現二者有...
摘要:并總結經典面試題集各種算法和插件前端視頻源碼資源于一身的文檔,優化項目,在瀏覽器端的層面上提升速度,幫助初中級前端工程師快速搭建項目。 本文是關注微信小程序的開發和面試問題,由基礎到困難循序漸進,適合面試和開發小程序。并總結vue React html css js 經典面試題 集各種算法和插件、前端視頻源碼資源于一身的文檔,優化項目,在瀏覽器端的層面上提升速度,幫助初中級前端工程師快...
閱讀 3707·2021-11-11 16:55
閱讀 1653·2021-10-08 10:04
閱讀 3588·2021-09-27 13:36
閱讀 2775·2019-08-30 15:53
閱讀 1865·2019-08-30 11:17
閱讀 1268·2019-08-29 16:55
閱讀 2105·2019-08-29 13:57
閱讀 2524·2019-08-29 13:13