微信小程序中多个页面传参通信的学习与实践


Posted in Javascript onMay 05, 2017

前言

微信小程序越来越火,不少公司都在将原生代码转为微信小程序代码。在开发过程中,由于微信小程序wx.navigateBack方法并不支持返回传参,导致一些页面,尤其是从列表页面跳入详情页,用户在详情页改变了状态,返回后无论是否刷新页面,体验都不是很好。在android中,我们一般采用setresult方法来返回参数,或者直接使用rxjava框架或者eventbus框架来解决此类问题。

业务分析

此类需求大概意思是:A页面进入B页面,B页面返回并传值给A。

探索之路

刚开始我想采用一个比较偷懒的方法,利用微信的wx.setStorage缓存在B页面存储,返回A页面,在onshow方法里调用wx.getStorage读取缓存来实现此功能。但是想想解决方式过于投机取巧,也会给日后维护带来大量隐患。
随后我在网上找到获取前一个page的方法,也可以实现此功能,部分代码如下:

var pages = getCurrentPages();
var currPage = pages[pages.length - 1]; //当前页面
var prevPage = pages[pages.length - 2]; //上一个页面

//直接调用上一个页面的setData()方法,把数据存到上一个页面中去
prevPage.setData({
 mdata:1 
})

仔细想了下,代码也不是很安全,因为进B页面的入口可能是多个,这样会导致获取的page出错。

本来是没招了,突然想到微信小程序支持js,然后就找了个轻量级的js库,而且是观察者模式,是我想要的类型。于是,好戏开始了

onfire.js介绍

onfire.js 是一个很简单的事件分发的Javascript库(仅仅 0.9kb),简洁实用。

github地址:https://github.com/hustcc/onfire.js [作者不是我]

本地下载地址:http://xiazai.3water.com/201705/yuanma/onfire.js(3water.com).rar

可以用于:

  • 简单的事件分发;
  • 在 react / vue.js / angular 用于跨组件的轻量级实现;
  • 事件订阅和发布;

实践

整理下思路如下:

  • A页面先订阅一个事件,并定义处理方法。
  • B页面返回时发送消息。
  • A页面卸载时,解除订阅。

A页面代码:

var onfire = require("../utils/onfire.js");
var that;
var eventObj = onfire.on('key', function () {
 //做具体的事
});

Page({
 data: {
 },
 onLoad: function(options) {
 // Do some initialize when page load.
 },
 onReady: function() {
 // Do something when page ready.
 },
 onUnload: function (e) {
 onfire.un('key');
 onfire.un(eventObj2);
 }
})

直接调用onfire.on方法订阅一个名字为key的消息,并且无传参。如果需要传参的话,直接在function里增加参数即可,如var eventObj = onfire.on('key', function (data)...

需要注意:一定要在onUnload里取消订阅key的消息,并取消绑定eventObj

B页面里代码在回调的地方加入

onfire.fire('key');//key为上文中订阅的消息
 //有参数时
 onfire.fire('key','test');

分析库代码

function _bind(eventName, callback, is_one, context) {
 if (typeof eventName !== string_str || typeof callback !== function_str) {
  throw new Error('args: '+string_str+', '+function_str+'');
 }
 if (! hasOwnKey(__onfireEvents, eventName)) {
  __onfireEvents[eventName] = {};
 }
 __onfireEvents[eventName][++__cnt] = [callback, is_one, context];

 return [eventName, __cnt];
 }

从代码中可以看出订阅on方法的时候实际调用_bind方法,该方法,主要是利用一个二维数组来存储订阅的对象。

function _fire_func(eventName, args) {
 if (hasOwnKey(__onfireEvents, eventName)) {
  _each(__onfireEvents[eventName], function(key, item) {
  item[0].apply(item[2], args); //执行订阅时的方法
  if (item[1]) delete __onfireEvents[eventName][key]; // 当类型为只订阅一次时,通知后即移除自己。
  });
 }
 }

fire发送消息方法实质调用_fire_func方法,通过名字key来遍历订阅者,然后通知订阅者。

function un(event) {
 var eventName, key, r = false, type = typeof event;
 if (type === string_str) {
  // 如果存在key值,则移除数组
  if (hasOwnKey(__onfireEvents, event)) {
  delete __onfireEvents[event];
  return true;
  }
  return false;
 }
 else if (type === 'object') {
  eventName = event[0];
  key = event[1];
  //如果找到这个对象则卸载
  if (hasOwnKey(__onfireEvents, eventName) && hasOwnKey(__onfireEvents[eventName], key)) {
  delete __onfireEvents[eventName][key];
  return true;
  }
  //否则返回false
  return false;
 }
 else if (type === function_str) {
  //两层循环来判断是否是方法名
  _each(__onfireEvents, function(key_1, item_1) {
  _each(item_1, function(key_2, item_2) {
   if (item_2[0] === event) {
   delete __onfireEvents[key_1][key_2];
   r = true;
   }
  });
  });
  return r;
 }
 return true;
 }

因为卸载支持按key、对象、方法卸载,所以需要先判断类型,然后按各自规则去解除绑定。

总结

有了这个事件分发库,很多问题游刃而解。好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
CSS+Table图文混排中实现文本自适应图片宽度(超简单+跨所有浏览器)
Feb 14 Javascript
Jquery 组合form元素为json格式,asp.net反序列化
Jul 09 Javascript
jQuery插件 tabBox实现代码
Feb 09 Javascript
js 连续赋值的简单实现
Jun 13 Javascript
javascript insertAfter()定义与用法示例
Jul 25 Javascript
HTML页面定时跳转方法解析(2种任选)
Dec 22 Javascript
jQuery Validate表单验证插件实现代码
Jun 08 jQuery
解决vue项目nginx部署到非根目录下刷新空白的问题
Sep 27 Javascript
Node.js控制台彩色输出的方法与原理实例详解
Dec 01 Javascript
node+multer实现图片上传的示例代码
Feb 18 Javascript
在Webpack中用url-loader处理图片和字体的问题
Apr 28 Javascript
JavaScript实现简单的音乐播放器
Aug 14 Javascript
微信小程序 开发之全局配置
May 05 #Javascript
jquery实现tab选项卡切换效果(悬停、下方横线动画位移)
May 05 #jQuery
微信小程序 图片上传实例详解
May 05 #Javascript
微信小程序实现登录页云层漂浮的动画效果
May 05 #Javascript
xmlplus组件设计系列之图标(ICON)(1)
May 05 #Javascript
xmlplus组件设计系列之网格(DataGrid)(10)
May 05 #Javascript
移动端web滚动分页的实现方法
May 05 #Javascript
You might like
一些操作和快捷键的理解和讨论
2020/03/04 星际争霸
PHP关联数组实现根据元素值删除元素的方法
2015/06/26 PHP
PHP结合Jquery和ajax实现瀑布流特效
2016/01/07 PHP
js 字符串转换成数字的三种方法
2013/03/23 Javascript
js使用栈来实现10进制转8进制与取除数及余数
2014/06/11 Javascript
node.js学习总结之调式代码的方法
2014/06/25 Javascript
JavaScript实现的一个日期格式化函数分享
2014/12/06 Javascript
jQuery带进度条全屏图片轮播特效代码分享
2020/06/28 Javascript
Jquery对新插入的节点 绑定Click事件失效的解决方法
2016/06/02 Javascript
js 颜色选择插件
2017/01/23 Javascript
JS得到当前时间的方法示例
2017/03/24 Javascript
ES6新特性之变量和字符串用法示例
2017/04/01 Javascript
JS路由跳转的简单实现代码
2017/09/21 Javascript
vue项目中vue-i18n和element-ui国际化开发实现过程
2018/04/25 Javascript
ES6中Set和Map数据结构,Map与其它数据结构互相转换操作实例详解
2019/02/28 Javascript
微信小程序 扭蛋抽奖机css3动画实现详解
2019/07/19 Javascript
[41:08]TNC vs VG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
[48:18]DOTA2-DPC中国联赛 正赛 RNG vs Dynasty BO3 第二场 1月29日
2021/03/11 DOTA
python通过ElementTree操作XML获取结点读取属性美化XML
2013/12/02 Python
Python Socket编程详细介绍
2017/03/23 Python
Django实现快速分页的方法实例
2017/10/22 Python
python数据批量写入ScrolledText的优化方法
2018/10/11 Python
Python产生Gnuplot绘图数据的方法
2018/11/09 Python
解决python3 requests headers参数不能有中文的问题
2019/08/21 Python
Python shelve模块实现解析
2019/08/28 Python
解决django接口无法通过ip进行访问的问题
2020/03/27 Python
CSS实现的一闪而过的图片闪光效果
2014/04/23 HTML / CSS
Html5实现如何在两个div元素之间拖放图像
2013/03/29 HTML / CSS
Pretty Green美国:英式摇滚服饰风格代表品牌之一
2019/01/23 全球购物
波兰品牌鞋履在线商店:Eastend.pl
2020/01/11 全球购物
酒店管理毕业生自我鉴定
2014/03/02 职场文书
基层党组织公开承诺书
2014/03/28 职场文书
卫生院健康教育实施方案
2014/06/07 职场文书
2016年小学中秋节活动总结
2016/04/05 职场文书
2017年寒假少先队活动总结
2016/04/06 职场文书
JavaScript原型链详解
2021/11/07 Javascript