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

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

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

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

  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/…

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

(0)

相关推荐

  • 微信小程序本地缓存数据增删改查实例详解

    微信小程序本地缓存数据增删改查实例详解 数据如: var user = { name: 'Lion', sex: 'guy' } CRUD: // 添加 wx.setStorageSync('user', user); // 查询 var developer = (wx.getStorageSync('user') || []); // 更改 developer.name = 'Lion01'; wx.setStorageSync('user', user); // 删除 wx.removeSt

  • 微信小程序实现给嵌套template模板传递数据的方式总结

    本文实例总结了微信小程序实现给嵌套template模板传递数据的方式.分享给大家供大家参考,具体如下: 一.template模板调用的数据是单一形态时: indexTemplate模板: <import src="../lookAndCollect-template/lookAndCollect-template.wxml" /> <template name="indexTemplate"> <view class="use

  • 微信小程序自定义组件的实现方法及自定义组件与页面间的数据传递问题

    首先我们在pages文件夹下创建components目录用于存放自定义组件.如图所示,以我创建的dialog组件为例,自定义组件的格式与页面一样,分为4个文件. 图1 图2 如上图2所示,假如index页面有一个按钮触发点击事件后弹出dialog,并且当点击某个部门时,将dialog关闭,并将部门名称与红色标题同步. 一.首先把dialog组件的样式写好,并在index页面相应的位置引用.以下就是代码啦(分别为:wxml.wxss.js.json) <view class='wx_dialog_

  • 微信小程序之数据双向绑定与数据操作

     微信小程序之数据双向绑定与数据操作 数据双向绑定是指js部分数据发生变化是html部分的数据也会发生变化,当然html部分数据发生变化js部分数据也会发生变化,从而使界面很方便的实现动态数据显示,一般拥有数据双向绑定的前端框架都为mvvm结构.数据双向绑定是个好东西,an1 an2 vue  也都有数据双向绑定的机制,而且基本都差不多,抄来抄去嘛!!下面以一个列表为例子来说下数据双向绑定及数据的操作. 1.把要进行数据双向绑定的属性放在page的data里,然后在html里使用{{属性名}}即

  • 微信小程序中使用ECharts 异步加载数据的方法

    官网例子都是同步的,怎么引入及同步demo请移步官网 <view class="container"> <ec-canvas id="mychart-dom-multi-bar" canvas-id="mychart-multi-bar" ec="{{ ecBar }}"></ec-canvas> <ec-canvas id="mychart-dom-multi-scatte

  • MAC系统利用charles抓取微信小程序和手机APP数据包(http和https数据包)

    本文中使用的是mac上的抓包工具charles进行抓包,手机是华为荣耀8 下载并安装Charles for Mac Charles for Mac(HTTP信息抓包工具) V4.2.5 苹果电脑版 要想抓取到微信小程序的数据首先要解决的第一个问题件就是如何通过charles抓取手机上的数据具体配置过程如下: MAC上的Charles设置 第一步,charles上通过proxy->proxy setting进入代理设置,入口如下图所示 点击后进入如下所示界面 记住此处的port,默认为8888,也

  • 小程序兼容安卓和IOS数据处理问题及坑

    最近开发微信小程序,遇到到过种坑,例如什么前端发送请求,后端请求成功,没有获取到前端传递的值:后端请求成功,并且值,前端就是出不来数据:请求接口出现Provision headers are shown的现象:到最后苹果手机上出现数据,安卓手机出现不了数据等等,非常多的bug.备注后端我用的php开发的,框架用的TP5.0,我一度怀疑是我框架的原因.安卓需要的是字符串,苹果好像都行吧,我是做的兼容处理. 作为一名程序员,连bug都没有,你还开发什么软件?废话不说了先上问题吧: 1.小程序前端发送

  • 微信小程序wx.request实现后台数据交互功能分析

    本文实例讲述了微信小程序wx.request实现后台数据交互功能.分享给大家供大家参考,具体如下: 记录微信小程序wx.request这个api在跟后台交互时遇上的问题. 1.根据资料,完成第一步,请求发送,代码如下: wx.request({ url: 'https://localhost:8443/xiaochengxu/addBill.do', data: e.detail.value, method: 'POST', success:function(res) { console.log

  • 微信小程序数据存储与取值详解

    在小程序开发的过程,经常要需要这个页面输入的数据,在下一个页面中进行取值赋值. 比如: 在A页面input输入框,输入电话号码,点击添加.需要在B页面电话区域中,显示刚刚输入的电话号码. 因为这是两个页面,就需要先存储,再取值.微信小程序提供了数据存储的API,wx.setStorage(OBJECT) 可以将数据存储在本地缓存中指定的 key 中,如果重复会覆盖掉原来该 key 对应的内容. 思路是,在A页面,使用bindinput获取input输入的值,赋值给一个变量(自定义),点击添加按钮

  • 微信小程序使用navigateTo数据传递的实例

    微信小程序使用navigateTo数据传递的实例 1,传递基本数据类型 index.js 发送页JS Page({ data: { testStr: '字符串str' }, onLoad: function () { }, next: function(e){ wx.navigateTo({ url: '/pages/test/test?str='+this.data.testStr, }) } }) test.js 接受页JS Page({ data:{ }, onLoad:function(

随机推荐