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


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 相关文章推荐
js异常捕获方法介绍
Apr 10 Javascript
html文档中的location对象属性理解及常见的用法
Aug 13 Javascript
JavaScript中Number.MIN_VALUE属性的使用示例
Jun 04 Javascript
用原生JS对AJAX做简单封装的实例代码
Jul 13 Javascript
Vue开发过程中遇到的疑惑知识点总结
Jan 20 Javascript
JavaScript 中Date对象的格式化代码方法汇总
Sep 06 Javascript
使用Vue.js和Flask来构建一个单页的App的示例
Mar 21 Javascript
webpack 样式加载的实现原理
Jun 12 Javascript
vue车牌号校验和银行校验实战
Jan 23 Javascript
ES6中的class是如何实现的(附Babel编译的ES5代码详解)
May 17 Javascript
记一次vue跨域的解决
Oct 21 Javascript
JS Object构造函数之Object.freeze
Apr 28 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使用Smarty的相关注意事项及访问变量的几种方式
2011/12/08 PHP
php在数据库抽象层简单使用PDO的方法
2015/11/03 PHP
php读取XML的常见方法实例总结
2017/04/25 PHP
php和html的区别点详细总结
2019/09/24 PHP
Firefox和IE浏览器兼容JS脚本写法小结
2008/07/07 Javascript
jquery动态改变onclick属性导致失效的问题解决方法
2013/12/04 Javascript
javascript中兼容主流浏览器的动态生成iframe方法
2014/05/05 Javascript
本人自用的global.js库源码分享
2015/02/28 Javascript
js获取鼠标位置实例详解
2015/12/09 Javascript
jQuery插件扩展extend的简单实现原理
2016/06/24 Javascript
谈谈JS中常遇到的浏览器兼容问题和解决方法
2016/12/17 Javascript
jQuery实现的省市联动菜单功能示例【测试可用】
2017/01/13 Javascript
jQuery、zepto、js常用小技巧
2017/02/12 Javascript
JS+DIV实现的卷帘效果示例
2017/03/22 Javascript
关于react中组件通信的几种方式详解
2017/12/10 Javascript
vue+vuex+axios+echarts画一个动态更新的中国地图的方法
2017/12/19 Javascript
vue.js 中使用(...)运算符报错的解决方法
2018/08/09 Javascript
GOJS+VUE实现流程图效果
2018/12/01 Javascript
vue router 组件的高级应用实例代码
2019/04/08 Javascript
vue实现移动端省市区选择
2019/09/27 Javascript
VUE 组件转换为微信小程序组件的方法
2019/11/06 Javascript
微信小程序仿淘宝热搜词在搜索框中轮播功能
2020/01/21 Javascript
javascript 易错知识点实例小结
2020/04/25 Javascript
使用npm命令提示: 'npm' 不是内部或外部命令,也不是可运行的程序的处理方法
2020/05/14 Javascript
Webpack5正式发布,有哪些新特性
2020/10/12 Javascript
[02:30]DOTA2英雄基础教程 暗影恶魔
2013/12/17 DOTA
[01:12:53]完美世界DOTA2联赛PWL S2 Forest vs SZ 第一场 11.25
2020/11/26 DOTA
Python两个整数相除得到浮点数值的方法
2015/03/18 Python
Django验证码的生成与使用示例
2017/05/20 Python
在Python的一段程序中如何使用多次事件循环详解
2017/09/07 Python
Django用户身份验证完成示例代码
2020/04/03 Python
Pytorch实现将模型的所有参数的梯度清0
2020/06/24 Python
项目采购员岗位职责
2014/04/15 职场文书
党的群众路线教育实践活动专题组织生活会发言材料
2014/10/17 职场文书
对学校的意见和建议
2015/06/04 职场文书
提档介绍信范文
2015/10/22 职场文书