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


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 相关文章推荐
Javascript的IE和Firefox兼容性汇编
Jul 01 Javascript
js下将字符串当函数执行的方法
Jul 13 Javascript
简单纯js实现点击切换TAB标签实例
Aug 23 Javascript
jQuery移动端图片上传组件
Jun 12 Javascript
jQuery实现iframe父窗体和子窗体的相互调用
Jun 17 Javascript
js删除Array数组中指定元素的两种方法
Aug 03 Javascript
js替换字符串中所有指定的字符(实现代码)
Aug 17 Javascript
javascript 实现文本使用省略号替代(超出固定高度的情况)
Feb 21 Javascript
JS解析后台返回的JSON格式数据实例
Aug 06 Javascript
简谈创建React Component的几种方式
Jun 15 Javascript
ElementUI Tag组件实现多标签生成的方法示例
Jul 08 Javascript
vue2路由基本用法实例分析
Mar 06 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
PHP源代码数组统计count分析
2011/08/02 PHP
php专用数组排序类ArraySortUtil用法实例
2015/04/03 PHP
PHP7安装Redis扩展教程【Linux与Windows平台】
2016/09/30 PHP
PDO::setAttribute讲解
2019/01/29 PHP
PHP接入微信H5支付的方法示例
2019/10/28 PHP
微信小程序发送订阅消息的方法(php 为例)
2019/10/30 PHP
TP5多入口设置实例讲解
2020/12/15 PHP
滚动经典最新话题[prototype框架]下编写
2006/10/03 Javascript
用js实现预览待上传的本地图片
2007/03/15 Javascript
checkbox 复选框不能为空
2009/07/11 Javascript
基于jQuery的判断iPad、iPhone、Android是横屏还是竖屏的代码
2014/05/11 Javascript
javascript实现切换td中的值
2014/12/05 Javascript
JavaScript中document对象使用详解
2015/01/06 Javascript
JavaScript中神奇的call()方法
2015/03/12 Javascript
jquery+ajax+text文本框实现智能提示完整实例
2016/07/09 Javascript
React.js中常用的ES6写法总结(推荐)
2017/05/09 Javascript
五步轻松实现zTree的使用
2017/11/01 Javascript
基于JavaScript实现简单的音频播放功能
2018/01/07 Javascript
微信小程序之swiper滑动面板用法示例
2018/12/04 Javascript
微信小程序从注册账号到上架(图文详解)
2019/07/17 Javascript
[00:35]2016完美“圣”典风云人物:冷冷宣传片
2016/12/08 DOTA
实例讲解Python中的私有属性
2014/08/21 Python
python3实现表白神器
2019/04/09 Python
python实现扫描ip地址的小程序
2019/04/16 Python
python3获取控制台输入的数据的具体实例
2020/08/16 Python
Python3+selenium配置常见报错解决方案
2020/08/28 Python
在pycharm中文件取消用 pytest模式打开的操作
2020/09/01 Python
学年自我鉴定范文
2013/10/01 职场文书
结婚喜宴家长答谢词
2014/01/15 职场文书
移风易俗倡议书
2014/04/15 职场文书
体育之星事迹材料
2014/05/11 职场文书
2014年大学教师工作总结
2014/12/02 职场文书
2015年大学生实习评语
2015/03/25 职场文书
《牧场之国》教学反思
2016/02/22 职场文书
opencv 分类白天与夜景视频的方法
2021/06/05 Python
CSS中妙用 drop-shadow 实现线条光影效果
2021/11/11 HTML / CSS