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


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 相关文章推荐
许愿墙中用到的函数
Oct 07 Javascript
extjs tabpanel限制选项卡数量实现思路及代码
Apr 02 Javascript
js 判断上传文件大小及格式代码
Nov 13 Javascript
浅析JavaScript事件和方法
Feb 28 Javascript
JS自定义选项卡函数及用法实例分析
Sep 02 Javascript
ajax级联菜单实现方法实例分析
Nov 28 Javascript
微信小程序 开发之滑块视图容器(swiper)详解及实例代码
Feb 22 Javascript
fullPage.js和CSS3实现全屏滚动效果
May 05 Javascript
微信小程序封装http访问网络库实例代码
May 24 Javascript
jquery中为什么能用$操作
Jun 18 jQuery
VsCode里的Vue模板的实现
Aug 12 Javascript
Vue使用CDN引用项目组件,减少项目体积的步骤
Oct 30 Javascript
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的十大要点(上)
2009/02/04 PHP
php统计时间和内存使用情况示例分享
2014/03/13 PHP
PHP MPDF中文乱码的解决方式
2015/12/08 PHP
PHP Callable强制指定回调类型的方法
2016/08/30 PHP
JavaScript中创建类/对象的几种方法总结
2013/11/29 Javascript
在每个匹配元素的外部插入新元素的方法
2013/12/20 Javascript
js判断iframe内的网页是否滚动到底部触发事件
2014/03/18 Javascript
微信企业号开发之微信考勤Cookies的使用
2015/09/11 Javascript
js实现的在线调色板功能完整实例
2016/12/21 Javascript
JS正则表达式验证密码格式的集中情况总结
2017/02/23 Javascript
js正则表达式验证密码强度【推荐】
2017/03/03 Javascript
微信小程序实现折叠展开效果
2018/07/19 Javascript
layui问题之模拟select点击事件的实例讲解
2018/08/15 Javascript
浅谈vue项目用到的mock数据接口的两种方式
2019/10/09 Javascript
JS实现transform实现扇子效果
2020/01/17 Javascript
小程序接入腾讯位置服务的详细流程
2020/03/03 Javascript
JS实现前端动态分页码代码实例
2020/06/02 Javascript
微信小程序文章详情功能完整实例
2020/06/03 Javascript
[37:29]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第二场 11.19
2020/11/19 DOTA
python进阶教程之循环对象
2014/08/30 Python
《Python之禅》中对于Python编程过程中的一些建议
2015/04/03 Python
python线程、进程和协程详解
2016/07/19 Python
pip install urllib2不能安装的解决方法
2018/06/12 Python
python 实现返回一个列表中出现次数最多的元素方法
2019/06/11 Python
pyqt5 实现多窗口跳转的方法
2019/06/19 Python
利用pyecharts实现地图可视化的例子
2019/08/12 Python
HTML5输入框下拉菜单功能的示例代码
2020/09/08 HTML / CSS
加拿大最大的相机店:Henry’s
2017/05/17 全球购物
在网络中有两台主机A和B,并通过路由器和其他交换设备连接起来,已经确认物理连接正确无误,怎么来测试这两台机器是否连通?如果不通,怎么来判断故障点?怎么排
2014/01/13 面试题
小区门卫管理制度
2014/01/29 职场文书
运动会通讯稿100字
2014/01/31 职场文书
护士个人自我鉴定
2014/03/24 职场文书
学生上课迟到检讨书
2015/01/01 职场文书
鲁迅故居导游词
2015/02/05 职场文书
「天才王子的赤字国家重生术」妮妮姆·拉雷粘土人开订
2022/03/21 日漫
Fluentd搭建日志收集服务
2022/09/23 Servers