黔优媒体网-软文媒体自助发稿平台!
  1. 行业资讯
  2. 正文

微信小程序中页面间通信的方式

来源:黔优媒体网   时间:2024-09-19

这篇文章主要介绍了微信小程序页面间通信的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: #39;hello from PageA #39;
 onShow() {
 // 页面初始化也会触发onShow,这种情况可能不需要检查通信
 if (isInitSelfShow) return;
 let newHello = wx.getStorageSync( #39;__data #39;);
 if (newHello) {
 this.setData({
 helloMsg: newHello
 // 清队上次通信数据
 wx.clearStorageSync( #39;__data #39;);
 onHide() {
 isInitSelfShow = false;
 goC() {
 wx.navigateTo({
 url: #39;/pages/c/c #39;
});
// pageC
Page({
 doSomething() {
 wx.setStorageSync( #39;__data #39;, #39;hello from PageC #39;);
});

优点:实现简单,容易理解

缺点:如果完成通信后,没有即时清除通信数据,可能会出现问题。另外因为依赖localStorage,而localStorage可能出现读写失败,从面造成通信失败

注意点:页面初始化时也会触发onShow

方式二:onShow/onHide + 小程序globalData

同方式一一样,利用onShow/onHide激活方法,通过读写小程序globalData完成数据传递

// PageA
let isInitSelfShow = true;
let app = getApp();
Page({
 data: {
 helloMsg: #39;hello from PageA #39;
 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: #39;/pages/c/c #39;
});
// PageC
let app = getApp();
Page({
 doSomething() {
 app.$$data.helloMsg = #39;hello from pageC #39;;
});

优点:实现简单,实现理解。因为不读写localStorage,直接操作内存,所以相比方式1,速度更快,更可靠

缺点:同方式1一样,要注意globalData污染

方式三:eventBus(或者叫PubSub)方式

这种方式要先实现一个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: #39;hello from PageA #39;
 onLoad() {
 app.pubSub.on( #39;hello #39;, (number) = {
 this.setData({
 helloMsg: #39;hello times: #39; + number
 goC() {
 wx.navigateTo({
 url: #39;/pages/c/c #39;
});
//pageC
let app = getApp();
let counter = 0;
Page({
 doSomething() {
 app.pubSub.emit( #39;hello #39;, ++counter);
 off() {
 app.pubSub.off( #39;hello #39;);
});

缺点:要非常注意重复绑定的问题

方式四:gloabelData watcher方式

前面提到方式中,我们有利用globalData完成通信。现在数据绑定流行,结合redux单一store的思想,如果我们直接watch一个globalData,那么要通信,只需修改这个data值,通过water去激活调用。同时修改的data值,本身就可以做为参数数据。

为了方便演示,这里使用oba这个开源库做为对象监控库,有兴趣的话,可以自己实现一个。

//pageA
import oba from #39;../../plugin/oba #39;;
let app = getApp();
Page({
 data: {
 helloMsg: #39;hello from PageA #39;
 onLoad() {
 oba(app.$$data, (prop, newvalue, oldValue) = {
 this.setData({
 helloMsg: #39;hello times: #39; + [prop, newvalue, oldValue].join( #39;# #39;)
 goC() {
 wx.navigateTo({
 url: #39;/pages/c/c #39;
});
//pageC
let app = getApp();
let counter = 0;
Page({
 doSomething() {
 app.$$data.helloTimes = ++counter;
});

优点:数据驱动,单一数据源,便于调试

缺点:重复watch的问题还是存在,要想办法避免

方式五:通过hack方法直接调用通信页面的方法

直接缓存页面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: #39;hello from PageA #39;
 onLoad() {
 app.pages.add(this);
 goC() {
 wx.navigateTo({
 url: #39;/pages/c/c #39;
 sayHello(msg) {
 this.setData({
 helloMsg: msg
});
//pageC
let app = getApp();
Page({
 doSomething() {
 // 见证奇迹的时刻
 app.pages.get( #39;pages/a/a #39;).sayHello( #39;hello u3xyz.com #39;);
});

优点:一针见血,功能强大,可以向要通信页面做你想做的任何事。无需要绑定,订阅,所以也就不存在重复的情况

缺点:使用了__route__这个hack属性,可能会有一些风险

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

微信小程序 页面跳转传参的介绍

微信小程序的页面跳转传值的实现

微信小程序 页面跳转和数据传递

以上就是微信小程序中页面间通信的方式的详细内容,更多请关注php中文网其它相关文章!

微信app下载

微信是一款手机通信软件,支持通过手机网络发送语音短信、视频、图片和文字。微信可以单聊及群聊,还能根据地理位置找到附近的人,带给大家全新的移动沟通体验,有需要的小伙伴快来保存下载体验吧!


【免责申明】黔优媒体网以上展示内容来源于用户自主上传、合作媒体、企业机构或网络收集整理,版权争议与本站无关,文章涉及见解与观点不代表黔优媒体网官方立场,请读者仅做参考,本文标题:微信小程序中页面间通信的方式;欢迎转载,转载时请说明出处。若您认为本文侵犯了您的版权信息,或您发现该内容有任何违法/违规的内容,请您立即联系我们及时修正或删除。(邮箱号: kefu@qianu.com)