详解小程序开发经验:多页面数据同步


Posted in Javascript onMay 18, 2019

导语:本文主要介绍在小程序中,多页面之间如何保持数据同步

在很多的产品中,都会存在跨页面间需要数据同步,如下示例:

详解小程序开发经验:多页面数据同步

为了更好的理解该场景,我们再详细描绘一下:

  1. 本场景包括4个页面:动态广场、个人中心、我的动态、动态详情
  2. 首先,进入动态广场页,请求加载数据,展示动态列表,其中,我们用绿色内阴影区分该条动态是“我的”,其他未加内阴影的表示是“别人的”;
  3. 然后,进入个人中心页,请求加载数据,展示获赞数量;
  4. 点击我的动态,进入我的动态页,请求加载数据,展示我的动态列表;
  5. 点击其中一条动态,进入动态详情页,请求加载数据,进行点赞操作;
  6. 在第5步中,点赞成功后,回退到我的动态页,可以看到该条动态点赞状态和数量发生变化,已经同步;
  7. 再回到到个人中心页,也可以看到获赞数量发生变化,已经同步;
  8. 再回到动态广场页,也可以看到对应的一条动态点赞状态和数量发生变化,已经同步;

下面我们来探讨一下这个场景的实现,在此之前,我们先要了解在点赞时,该场景中各页面的状态及关系。

详解小程序开发经验:多页面数据同步

详解小程序开发经验:多页面数据同步

如上图所示,当我们在点赞时,4个页面都已经在是打开的(4个webview)。当我们点赞成功时,点击左上解返回时,动态详情页的webview关掉,直接看到下一层webview,也就是我的动态页,这个页面是已经存在的。其他页面也是如此。
那对于这些已经存在的页面,我们应该如何同步更新数据呢?

当然,如果比较懒,可以直接在onShow的时候重新拉数据渲染页面。但显然这是非常低级、不可取也没必要的做法。重新拉数据需要耗时,页面重新渲染也会看到闪屏,关键是根本没必要重新拉数据,因为数据发生了变化,前端是知道的。

所以我们可以这样做,在动态详情页点赞成功时,保存一个数据到全局globalData中去,回到我的动态页,在onShow中去检测全局globalData中是否有点赞变化的数据,有的话,就读取出来去更新相应的动态。

// 动态详情页js
onLike() {
 ...
 success: () => {
 App.globalData.like = {
  fid: 10001,
  likes: 1,
  hasLike: true   
 }
 }
}

// 我的动态页js
onShow() {
 if(App.globalData.like !== null) {
 // 读取globaldata.like数据去更新
 this.doUpdata()
 // 特别需要注意,更新完后,需要把globaldata.like清掉,不然下次onShow还会继续走到该逻辑
 App.globalData.like = null
 }
}

这样似乎可以达到我们的目的,无请求、纯前端局部更新。

但这样还存在一个问题,当我们再退回到个人中心页时,要检查下获赞数量是否需要更新,以及回到动态广场页时,也要检查点赞有没有发生变化。但在这两个页面onShow去判断App.globalData.like时,都已经检测不到了,因为该数据已经在我的动态页onShow中置为null了。

概括来说,在点赞时,只生产了一条数据,但有多个消费者,哪个页面先把数据消费了,其他页面也就无法检测到数据了。

由此,我们想到那就使用EventBus来处理。
首先,我们自己实现一套简单的EventBus。

源码见:git.weixin.qq.com/xinyuanliu/…

在小程序启动时,初始化EventBus:

const Event = require('/util/events.js').default

App({
 events: null,
 onLaunch(options) {
 this.initEvents()
 // doOtherThings
 },
 initEvents() {
 this.events = new Event()
 },
 emitFeedsLike(data) {
 this.events.emit('feedsLike', data)
 },
 emitPublishFeeds(data) {
 this.events.emit('publishFeeds', data)
 },
 ...
}

各个页面在onLoad时,注册监听事件(在此以我的动态页为例):

// 我的动态.js
const App = getApp()

Page({
 data: {
 list: []
 },
 onLoad: function (options) {
 ...
 // 监听点赞事件广播
 ↓ 重点在这里 ↓
 App.events.on('feedsLike', data => {
  console.log('我的动态页面收到点赞变化通知:', data)
  // 进行更新操作
 })
 // 监听发布事件广播
 ↓ 重点在这里 ↓
 App.events.on('publishFeeds', data => {
  console.log('我的动态页面收到发布动态通知:', data)
  // 进行更新操作
 })
 },
 ...
})

然后在动态点赞时,发出事件通知。(这里一条动态是封装成组件,不属于某一个页面,点赞事件也是封装在组件内)

const App = getApp()

Component({
 properties: {...},
 methods: {
 // 点赞
 tapLike(e) {
  let { likes, hasLike } = this.data

  likes += (hasLike && -1 || 1)
  hasLike = !hasLike

  this.updateFeeds(likes, hasLike).then(() => {
  this.setData({
   likes,
   hasLike
  })

  // 广播事件
  ↓ 重点在这里 ↓
  App.emitFeedsLike({
   uid: this.data.uid,
   fid: this.data.fid,
   likes,
   hasLike
  })
  })
 },
 ...
 }
})

这样,我们便在小程序中实现了一套跨页面数据同步的方案。

直观上这已经非常完美的实现了我们的需求。但在小程序中存在一个与我们常规经验不太一致的地方。那就是页面在关掉后,它里面的对象并没有销毁,这点是因为小程序的逻辑层是共用一个进程。

详解小程序开发经验:多页面数据同步

因此,每次进入页面,都会注册一次监听事件,而退出页面后,该事件并不会销毁。这样的话,多次重复进入页面,就会注册多个重复事件,当事件发生时,就会执行多次响应。请仔细观察下图!

详解小程序开发经验:多页面数据同步

为了避免该现象出现,我们切记要在页面的onUnload事件中,主动销毁监听事件。

Page({
 eventsListener: {},
 data: {
 list: []
 },
 onLoad: function (options) {
 ...
 // 监听点赞事件广播
 ↓ 重点在这里 ↓
 this.eventsListener.feedsLike = App.events.on('feedsLike', data => {
  console.log('我的动态页面收到点赞变化通知:', data)
  // 进行更新操作
 })
 // 监听发布事件广播
 ↓ 重点在这里 ↓
 this.eventsListener.publishFeeds= App.events.on('publishFeeds', data => {
  console.log('我的动态页面收到发布动态通知:', data)
  // 进行更新操作
 })
 },
 ↓ 重点在这里 ↓
 onUnload() {
 for (let i in this.eventsListener) {
  App.events.remove(i, this.eventsListener[i])
 } 
 },
 ...
})

至此,我们在小程序中完美的实现了跨页面/组件、多页面数据同步。

本文研究的demo均可以小程序中体验,项目源码:git.weixin.qq.com/xinyuanliu/…

以上所述是小编给大家介绍的小程序开发经验:多页面数据同步详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jquery.jstree 增加节点的双击事件代码
Jul 27 Javascript
初窥JQuery-Jquery简介 入门了解篇
Nov 25 Javascript
JQuery+DIV自定义滚动条样式的具体实现
Jun 25 Javascript
浅谈javascript中onbeforeunload与onunload事件
Dec 10 Javascript
JavaScript基础——使用Canvas绘图
Nov 02 Javascript
js手机号批量滚动抽奖实现代码
Apr 17 Javascript
JavaScript mixin实现多继承的方法详解
Mar 30 Javascript
Vue.js图片预览插件使用详解
Aug 27 Javascript
vue动画打包后失效问题的解决方法
Sep 18 Javascript
基于vue开发微信小程序mpvue-docs跳转页面功能
Apr 10 Javascript
原生JS与JQ获取元素的区别详解
Feb 13 Javascript
jQuery-App输入框实现实时搜索
Nov 19 jQuery
JavaScript实现星级评价效果
May 17 #Javascript
JavaScript实现美化滑块效果
May 17 #Javascript
vue中使用mxgraph的方法实例代码详解
May 17 #Javascript
vue中引入mxGraph的步骤详解
May 17 #Javascript
微信小程序云开发 搭建一个管理小程序
May 17 #Javascript
微信小程序云开发实现增删改查功能
May 17 #Javascript
微信小程序云开发实现云数据库读写权限
May 17 #Javascript
You might like
PHP 和 MySQL 开发的 8 个技巧
2007/01/02 PHP
php防注入及开发安全详细解析
2013/08/09 PHP
删除重复数据的算法
2006/11/23 Javascript
js Array对象的扩展函数代码
2013/04/24 Javascript
js中如何复制一个对象并获取其所有属性和属性对应的值
2013/10/24 Javascript
将JSON字符串转换成Map对象的方法
2016/11/30 Javascript
JS身份证信息验证正则表达式
2017/06/12 Javascript
AngularJS实现的JSONP跨域访问数据传输功能详解
2017/07/20 Javascript
微信小程序实现折线图的示例代码
2019/06/07 Javascript
使用layer.msg 时间设置不起作用的解决方法
2019/09/12 Javascript
vue iview实现动态新增和删除
2020/06/17 Javascript
vue tab滚动到一定高度,固定在顶部,点击tab切换不同的内容操作
2020/07/22 Javascript
nuxt.js添加环境变量,区分项目打包环境操作
2020/11/06 Javascript
Vue3配置axios跨域实现过程解析
2020/11/25 Vue.js
Python编码时应该注意的几个情况
2013/03/04 Python
python编写爬虫小程序
2015/05/14 Python
深入理解 Python 中的多线程 新手必看
2016/11/20 Python
Python实现的当前时间多加一天、一小时、一分钟操作示例
2018/05/21 Python
详解python里的命名规范
2018/07/16 Python
Python3解释器知识点总结
2019/02/19 Python
详解Python数据可视化编程 - 词云生成并保存(jieba+WordCloud)
2019/03/26 Python
在Python中字符串、列表、元组、字典之间的相互转换
2019/11/15 Python
HTML5无刷新改变当前url的代码
2017/03/15 HTML / CSS
网购亚洲时装、美容产品和生活百货:YesStyle
2016/09/15 全球购物
美国领先的奢侈手表在线零售商:WatchMaxx
2017/12/17 全球购物
AP澳洲中文网:澳洲正品直邮,包税收件无忧
2019/07/12 全球购物
家乐福台湾线上购物网:Carrefour台湾
2020/09/15 全球购物
日语专业推荐信
2013/11/12 职场文书
初婚未育未抱养证明
2014/01/12 职场文书
市场营销管理毕业生自荐信
2014/03/03 职场文书
关于雷锋的演讲稿
2014/05/10 职场文书
知识竞赛拉拉队口号
2014/06/16 职场文书
社区服务活动小结
2014/07/08 职场文书
大学生党员暑假实践(活动总结)
2019/08/21 职场文书
基于angular实现树形二级表格
2021/10/16 Javascript
Windows server 2012 配置Telnet以及用法详解
2022/04/28 Servers