小程序跨页面交互的作用与方法详解


Posted in Javascript onJanuary 07, 2020

去年年末,微信小程序的分包大小已经到达了 12M 大小,一方面说明小程序的确逐步为开发者放开更大的权限,另一方面也说明了对于某些小程序 8M 的大小已经不够用了。我个人今年也是在开发一个 to B 小程序应用。这里列举一些跨页面交互的场景。

对于 B 端应用的业务需求来说,小程序开发的复杂度相对比网页开发要复杂一些。一个是双线程的处理机制问题,另一个是页面栈之间交互问题。

注: 笔者目前只需要开发微信小程序,为了在小程序页面中可以使用 properties behaviors observers 等新功能,已经使用 Component 构造器来构造页面。具体可以参考微信小程序 Component 构造器。如果你也没有多端开发的需求,建议尝试使用,可以得到不错的体验。

性能优化类

对于小程序在页面中点击触发 wx.navigateTo 跳转其他页面,中间会有一段时间的空白加载期(对于分包出去的页面,空白期则会更长),但是这是小程序内部机制,没有办法进行优化。我们只能眼睁睁的等待这段没有意思的空白期过去。

当考虑到跳转页面后的第一件事情便是取数逻辑,那么我们是否能够进行优化呢?答案是肯定的。我们没有办法直接在当前页面取得数据之后再进行跳转操作(这样操作更不好),但是我们却可以利用缓存当前的请求,详情可以参考我之前的博客文章 ——Promise对象 3 种妙用。

代码如下:

const promiseCache = new Map()

export function setCachePromise(key, promise) {
 promiseCache.set(key, promise)
}

export function getCachePromise(key) {
 // 根据key获取当前的数据 
 const promise = promiseCache.get(key)
 // 用完删除,目前只做中转用途,也可以添加其他用途
 promiseCache.delete(key)
 return promise 
}

做一份全局的 Map,然后利用 Map 缓存 promise 对象,在跳转之前代码为:

// 导入 setCachePromise 函数

Component({
 methods: {
 getBookData(id) {
  const promise = // promise 请求
  setCachePromise(`xxx:${id}`, promise)  
 }, 
 handleBookDetailShow(e) {
  const id = e.detail
  this.getBookData(id)
  wx.navigateTo({url: `xx/xx/x?id=${id}`})
 }
 }
})

而跳转之后的代码也如下所示:

// 导入 getCachePromise 函数

Component({
 properties: {
  id: Number 
 },
 lifetimes: {
  attached () {
  const id = this.data.id 
  // 取得全局缓存的promise
  const bookPromise = getCachePromise(`xxx:${id}`)
  bookPromise.then((res) => {
   // 业务处理
  }).catch(error => {
   // 错误处理 
  })
  }
 },
 methods: {
  getBook() {
  // 获取数据,以便于 错误处理 上拉刷新 等操作 
  } 
 }
})

如此便可以同时处理取数和页面加载的逻辑,当然,这个对于页面有耦合性,不利于后续的删除与修改。但考虑如果仅仅加在分包跳转之间可能会有不错的效果。

想要无侵入式,可以进一步学习研究 微信小程序之提高应用速度小技巧 以及 wxpage 框架,同时考虑到无论是 ToC 还是 ToC 用户,都有可能存在硬件以及网络环境等问题,该优化还是非常值得的。

当然微信小程序为了减少冷启动时间,提供了周期性更新 数据预拉取 功能。

注: 上面的 promiseCache 只作为中转的用途,不作为缓存的用途,如果你考虑添加缓存,可以参考我之前的博客文章—— 前端 api 请求缓存方案。

通知类

如果是 pc 端中进行交互,对于数据的 CRUD。例如在详情页面进行了数据的修改和删除,返回列表时候就直接调取之前存储的列表查询条件再次查询即可,而对于移动端这种下拉滚动的设计,就没有办法直接调用之前的查询条件来进行搜索。

如果从列表页面进入详情页面后,在详情页面只会进行添加或者修改操作。然后返回列表页面。此时可以提示用户数据已经进行了修改,请用户自行决定是否进行刷新操作。

如在编辑页面修改了数据:

const app = getApp()

component({
 methods: {
 async handleSave() {
  //...
  app.globalData.xxxChanged = true
  //... 
 }
 }
})

列表界面:

const app = getApp()

component({
 pageLifetimes: {
 show() {
  this.confirmThenRefresh()
 } 
 },
 methods: {
 confirmThenRefresh() {
  // 检查 globalData,如果当前没有进行修改,直接返回 
  if(!app.globalData.xxxChanged) return
  wx.showModal({
  // ...
  complete: () => {
   // 无论确认刷新与否,都把数据置为 false 
   app.globalData.xxxChanged = false 
  } 
  }) 
 }
 } 
})

当然了,我们也可以利用 wx.setStorage 或者 getCurrentPage 获取前面的页面 setData 来进行数据通知,以便用户进行页面刷新。

订阅发布类

如果仅仅只涉及到修改数据的前提下,我们可以选择让用户进行刷新操作,但是如果针对于删除操作而言,如果用户选择不进行刷新,然后用户又不小心点击到了已经被删除的数据,就会发生错误。所以如果有删除的需求,我们最好在返回列表页面前就进行列表的修改,以免造成错误。

mitt

github 上有很多的 pub/sub 开源库,如果没有什么特定的需求,找到代码量最少的就是 mitt 这个库了,作者是喜欢开发微型库的 developit 大佬,著名的 preact 也是出于这位大佬之手。 这里就不做过多的介绍,非常简单。大家可能都能看明白,代码如下(除去 flow 工具的检查):

export default function mitt(all) {
 all = all || Object.create(null);

 return {
 on(type, handler) {
  (all[type] || (all[type] = [])).push(handler);
 },

 off(type, handler) {
  if (all[type]) {
  all[type].splice(all[type].indexOf(handler) >>> 0, 1);
  }
 },
 emit(type, evt) {
  (all[type] || []).slice().map((handler) => { handler(evt); });
  (all['*'] || []).slice().map((handler) => { handler(type, evt); });
 }
 };
}

仅仅只有3个方法,on emit以及 off。

只要在多个页面导入 生成的 mitt() 函数生成的对象即可(或者直接放入 app.globalData 中也可)。

Component({
 lifetimes: {
 attached: function() {
  // 页面创建时执行
  const changeData = (type, data) => {
  // 处理传递过来的类型与数据
  }
  this._changed = changeData
  bus.on('xxxchanged', this._changed)
 },
 detached: function() {
  // 页面销毁时执行
  bus.off('xxxchanged', this._changed)
 }
 }
})

这里mitt可以有多个页面进行绑定事件,如果需求仅仅只涉及到两个页面之间,我们就可以使用 wx.navigateTo 中的 EventChannel (页面间事件信息通道)。可以参考微信小程序wx.navigateTo方法里的events参数使用详情及场景,该方案的利好在于,传递到下一个页面的参数也可以通过 EventChannel 来通知,以便于解决 properties 传递数据不宜过大的问题。

注: 一个页面展示很多信息的时候,会造成小程序页面的卡顿以及白屏。小程序官方也有长列表组件 recycle-view。有需求的情况下可以自行研究,这个不在这里详述。

鼓励一下

如果你觉得这篇文章不错,希望可以给与我一些鼓励,在我的 github 博客下帮忙 star 一下。
博客地址

参考文档

wxpage

mitt

Promise对象 3 种妙用

前端 api 请求缓存方案

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
SOSO地图JS画出标注和中心点以html形式运行
Aug 09 Javascript
原生JS实现加入收藏夹的代码
Oct 24 Javascript
jQuery表格插件ParamQuery简单使用方法示例
Dec 05 Javascript
JQuery的ON()方法支持的所有事件罗列
Feb 28 Javascript
js漂浮广告实现代码
Aug 15 Javascript
5个最顶级jQuery图表类库插件【jquery插件库】
May 05 Javascript
JavaScript使用atan2来绘制箭头和曲线的实例
Sep 14 Javascript
jQuery完成表单验证的实例代码(纯代码)
Sep 30 jQuery
详解vuex中mapState,mapGetters,mapMutations,mapActions的作用
Apr 13 Javascript
JS中‘hello’与new String(‘hello’)引出的问题详解
Aug 14 Javascript
Vue CLI 3搭建vue+vuex最全分析(推荐)
Sep 27 Javascript
ES6 Promise对象的应用实例分析
Jun 27 Javascript
JavaScript实现联动菜单特效
Jan 07 #Javascript
JS实现电商商品展示放大镜特效
Jan 07 #Javascript
JS实现字体背景跑马灯
Jan 06 #Javascript
JS实现音乐钢琴特效
Jan 06 #Javascript
React Native中ScrollView组件轮播图与ListView渲染列表组件用法实例分析
Jan 06 #Javascript
Vue-CLI与Vuex使用方法实例分析
Jan 06 #Javascript
Vue前端项目部署IIS的实现
Jan 06 #Javascript
You might like
《被神捡到的男人》动画化计划进行中!
2020/03/06 日漫
php 截取字符串并以零补齐str_pad() 函数
2011/05/07 PHP
php设计模式 Facade(外观模式)
2011/06/26 PHP
对于PHP 5.4 你必须要知道的
2013/08/07 PHP
PHP 7的一些引人注目的新特性简单介绍
2015/11/08 PHP
使用javascript访问XML数据的实例
2006/12/27 Javascript
Easy.Ajax 部分源代码 支持文件上传功能, 兼容所有主流浏览器
2011/02/24 Javascript
jQuery实现带滚动线条导航效果的方法
2015/01/30 Javascript
js实现精美的图片跟随鼠标效果实例
2015/05/16 Javascript
轻松学习jQuery插件EasyUI EasyUI表单验证
2015/12/01 Javascript
探究JavaScript函数式编程的乐趣
2015/12/14 Javascript
jquery插件EasyUI中form表单提交实例分享
2016/01/11 Javascript
JavaScript数组合并的多种方法
2016/05/22 Javascript
NodeJS自定义模块写法(详解)
2017/06/27 NodeJs
JS对象序列化成json数据和json数据转化为JS对象的代码
2017/08/23 Javascript
JavaScript函数的4种调用方法实例分析
2019/03/05 Javascript
js实现简单选项卡制作
2020/08/05 Javascript
快速解决Vue、element-ui的resetFields()方法重置表单无效的问题
2020/08/12 Javascript
解决vant的Toast组件时提示not defined的问题
2020/11/11 Javascript
Python修改Excel数据的实例代码
2013/11/01 Python
Python中if __name__ == '__main__'作用解析
2015/06/29 Python
Python实现基本数据结构中栈的操作示例
2017/12/04 Python
python OpenCV学习笔记之绘制直方图的方法
2018/02/08 Python
关于django 数据库迁移(migrate)应该知道的一些事
2018/05/27 Python
pandas求两个表格不相交的集合方法
2018/12/08 Python
Python爬虫:url中带字典列表参数的编码转换方法
2019/08/21 Python
python生成器推导式用法简单示例
2019/10/08 Python
会计毕业生求职简历的自我评价
2013/10/20 职场文书
测绘工程个人的自我评价
2013/11/10 职场文书
自我评价中英文语句
2013/11/30 职场文书
酒吧副总经理岗位职责
2013/12/10 职场文书
社区学习雷锋活动总结
2014/04/25 职场文书
中秋节晚会开场白
2015/05/29 职场文书
争做文明公民倡议书
2019/06/24 职场文书
mysql 直接拷贝data 目录下文件还原数据的实现
2021/07/25 MySQL
Android RecyclerView实现九宫格效果
2022/06/28 Java/Android