文章目录
前言1.页面通信分类 一、GET类通信二、POST类通信三、localStorage通信四、全局参数通信五、发布订阅中间件六、oba开源库七、hack方法总结前言
在小程序中如果一个页面由另一个页面通过 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.typelet typename=options.typename}
二、POST类通信
const app = getApp()Page({jump: function () {wx.navigateTo({url: './test',events: {//监听父acceptDataFromOpenedPageacceptDataFromOpenedPage: function (data) {console.log(data)},},success: function (res) {//触发子acceptDataFromOpenerPageres.eventChannel.emit('acceptDataFromOpenerPage', {data: 'send from opener page' })}})},})
Page({onLoad: function (option) {//获取EventChannel对象const eventChannel = this.getOpenerEventChannel()// 触发父acceptDataFromOpenedPageeventChannel.emit('acceptDataFromOpenedPage', {data: 'send from opened page' });// 监听子acceptDataFromOpenerPageeventChannel.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});}});
//pageClet app = getApp();Page({doSomething() {// 见证奇迹的时刻app.pages.get('pages/a/a').sayHello('hello ');}});