写点什么

【愚公系列】2022 年 11 月 微信小程序 - 页面间通信

作者:愚公搬代码
  • 2022-11-23
    福建
  • 本文字数:3179 字

    阅读完需:约 10 分钟

前言

在小程序中如果一个页面由另一个页面通过 wx.navigateTo 打开,这两个页面间将建立一条数据通道:被打开的页面可以通过 this.getOpenerEventChannel() 方法来获得一个 EventChannel 对象;wx.navigateTo 的 success 回调中也包含一个 EventChannel 对象。这两个 EventChannel 对象间可以使用 emit 和 on 方法相互发送、监听事件。

1.页面通信分类

按页面层级(或展示路径)可以分为:


兄弟页面间通信。如多 Tab 页面间通信,PageA,PageB 之间通信


  • 父路径页面向子路径页面通信,如 PageA 向 PageC 通信

  • 子路径页面向父路径页面通信,如 PageC 向 PageA 通信


按通信时激活对方方法时机,又可以分为:


  • 延迟激活,即我在 PageC 做完操作,等返回到 PageA 再激活 PageA 的方法调用

  • 立即激活,即我在 PageC 做完操作,在 PageC 激活 PageA 的方法调用

一、GET 类通信

<view class="border-black margin-left-right-25" style="flex:1"                               bindtap="testDrive" data-type="{{item.type}}" data-typename="{{item.typename}}">预约试驾</view>
复制代码


testDrive: function (e) {  var type = e.currentTarget.dataset.type;  var typename = e.currentTarget.dataset.typename;  wx.navigateTo({      url: '/pages/sales/sales-test?type=' + type + "&typename=" + typename,  //值的传递  })},//在sales-test.js页面进行获取传递过来的值onLoad: function (options) {  let type= options.type  let typename=options.typename}
复制代码

二、POST 类通信

const app = getApp()
Page({ jump: function () { wx.navigateTo({ url: './test', events: { //监听父acceptDataFromOpenedPage acceptDataFromOpenedPage: function (data) { console.log(data) }, }, success: function (res) { //触发子acceptDataFromOpenerPage res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'send from opener page' }) } }) },})
复制代码


Page({  onLoad: function (option) {    //获取EventChannel对象    const eventChannel = this.getOpenerEventChannel()    // 触发父acceptDataFromOpenedPage    eventChannel.emit('acceptDataFromOpenedPage', { data: 'send from opened page' });    // 监听子acceptDataFromOpenerPage    eventChannel.on('acceptDataFromOpenerPage', function (data) {      console.log(data)    })  }})
复制代码

三、localStorage 通信

// pageAlet 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' }); }});
复制代码


// pageCPage({ doSomething() {  wx.setStorageSync('__data', 'hello from PageC'); }});
复制代码


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

四、全局参数通信

// PageAlet 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' }); }});
复制代码


// PageClet app = getApp();
Page({ doSomething() { app.$$data.helloMsg = 'hello from pageC'; }});
复制代码


注意点:要注意 globalData 污染

五、发布订阅中间件

/* /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]); }}
复制代码


//pageAlet 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' }); }});
复制代码


//pageClet app = getApp();let counter = 0;
Page({ doSomething() { app.pubSub.emit('hello', ++counter); },
off() { app.pubSub.off('hello'); }});
复制代码


注意点:重复绑定的问题

六、oba 开源库

//pageAimport 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' }); }});
复制代码


//pageClet app = getApp();let counter = 0;
Page({ doSomething() { app.$$data.helloTimes = ++counter; }});
复制代码


注意点:重复 watch 的问题

七、hack 方法

每个页面有 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__; }}
复制代码


// pageAlet 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'); }});
复制代码

总结

  • GET 类通信

  • POST 类通信

  • localStorage 通信

  • 全局参数通信

  • 发布订阅中间件

  • oba 开源库

  • hack 方法

发布于: 刚刚阅读数: 5
用户头像

还未添加个人签名 2022-03-01 加入

该博客包括:.NET、Java、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、python、大数据等相关使用及进阶知识。查看博客过程中,如有任何问题,皆可随时沟通。

评论

发布
暂无评论
【愚公系列】2022年11月 微信小程序-页面间通信_11月月更_愚公搬代码_InfoQ写作社区