海拔科技 高企
湖南长沙海拔科技联系电话 17373127962
bg
联系我们
海拔科技

地址:长沙市开福区万达总部国际A栋44003A

电话:17373127962

邮箱:zealotxp@qq.com

小程序开发经验:多页面数据同步
时间:2019-06-19 12:03 浏览次数:
【摘要】在很多的产品中,都会存在跨页面间需要数据同步,如下示例: 为了更好的理解该场景,我们再详细描绘一下: 本场景包括4个页面:动态广场、个人中心、我的动态、动态详情 1.首先

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

  

 为了更好的理解该场景,我们再详细描绘一下:
       本场景包括4个页面: 动态广场、 个人中心、 我的动态、 动态详情
1.首先,进入 动态广场页,请求加载数据,展示动态列表,其中,我们用绿色内阴影区分该条动态是“我的”,其他未加内阴影的表示是“别人的”;
2.然后,进入 个人中心页,请求加载数据,展示获赞数量;
3.点击我的动态,进入 我的动态页,请求加载数据,展示我的动态列表;
4.点击其中一条动态,进入 动态详情页,请求加载数据,进行 点赞操作;
5.在第5步中,点赞成功后,回退到 我的动态页,可以看到该条动态点赞状态和数量发生变化,已经同步;
6.再回到到 个人中心页,也可以看到获赞数量发生变化,已经同步;
7.再回到 动态广场页,也可以看到对应的一条动态点赞状态和数量发生变化,已经同步。
下面我们来探讨一下这个场景的实现,在此之前,我们先要了解在点赞时,该场景中各页面的状态及关系。



       如上图所示,当我们在点赞时,4个页面都已经在是打开的(4个 webview)。当我们点赞成功时,点击左上解返回时, 动态详情页的 webview关掉,直接看到下一层 webview,也就是 我的动态页,这个页面是已经存在的。其他页面也是如此。

       那对于这些已经存在的页面,我们应该如何同步更新数据呢?

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

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


  1. // 动态详情页js

  2. onLike() {

  3. ...

  4. success: () => {

  5. App.globalData.like = {

  6. fid: 10001,

  7. likes: 1,

  8. hasLike: true

  9. }

  10. }

  11. }

  12.  

  13. // 我的动态页js

  14. onShow() {

  15. if(App.globalData.like !== null) {

  16. // 读取globaldata.like数据去更新

  17. this.doUpdata()

  18. // 特别需要注意,更新完后,需要把globaldata.like清掉,不然下次onShow还会继续走到该逻辑

  19. App.globalData.like = null

  20. }

  21. }

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

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

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

       由此,我们想到那就使用 EventBus来处理。

       首先,我们自己实现一套简单的EventBus。

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


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

  2.  

  3. App({

  4. events: null,

  5. onLaunch(options) {

  6. this.initEvents()

  7. // doOtherThings

  8. },

  9. initEvents() {

  10. this.events = new Event()

  11. },

  12. emitFeedsLike(data) {

  13. this.events.emit('feedsLike', data)

  14. },

  15. emitPublishFeeds(data) {

  16. this.events.emit('publishFeeds', data)

  17. },

  18. ...

  19. }

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


  1. // 我的动态.js

  2. const App = getApp()

  3.  

  4. Page({

  5. data: {

  6. list: []

  7. },

  8. onLoad: function (options) {

  9. ...

  10. // 监听点赞事件广播

  11. ↓ 重点在这里 ↓

  12. App.events.on('feedsLike', data => {

  13. console.log('我的动态页面收到点赞变化通知:', data)

  14. // 进行更新操作

  15. })

  16. // 监听发布事件广播

  17. ↓ 重点在这里 ↓

  18. App.events.on('publishFeeds', data => {

  19. console.log('我的动态页面收到发布动态通知:', data)

  20. // 进行更新操作

  21. })

  22. },

  23. ...

  24. })

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


  1. const App = getApp()

  2.  

  3. Component({

  4. properties: {...},

  5. methods: {

  6. // 点赞

  7. tapLike(e) {

  8. let { likes, hasLike } = this.data

  9.  

  10. likes += (hasLike && -1 || 1)

  11. hasLike = !hasLike

  12.  

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

  14. this.setData({

  15. likes,

  16. hasLike

  17. })

  18.  

  19. // 广播事件

  20. ↓ 重点在这里 ↓

  21. App.emitFeedsLike({

  22. uid: this.data.uid,

  23. fid: this.data.fid,

  24. likes,

  25. hasLike

  26. })

  27. })

  28. },

  29. ...

  30. }

  31. })

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

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

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

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

  1. Page({

  2. eventsListener: {},

  3. data: {

  4. list: []

  5. },

  6. onLoad: function (options) {

  7. ...

  8. // 监听点赞事件广播

  9. ↓ 重点在这里 ↓

  10. this.eventsListener.feedsLike = App.events.on('feedsLike', data => {

  11. console.log('我的动态页面收到点赞变化通知:', data)

  12. // 进行更新操作

  13. })

  14. // 监听发布事件广播

  15. ↓ 重点在这里 ↓

  16. this.eventsListener.publishFeeds= App.events.on('publishFeeds', data => {

  17. console.log('我的动态页面收到发布动态通知:', data)

  18. // 进行更新操作

  19. })

  20. },

  21. ↓ 重点在这里 ↓

  22. onUnload() {

  23. for (let i in this.eventsListener) {

  24. App.events.remove(i, this.eventsListener[i])

  25. }

  26. },

  27. ...

  28. })

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

海拔科技,长沙小程序定制开发,长沙APP定制开发,长沙APP制作开发,长沙小程序制作开发,长沙微信开发,长沙网络公司,长沙信息公司,小程序

标签:
keywords:长沙小程序开发 长沙小程序制作 长沙APP开发 长沙网站建设 长沙网络推广 长沙软件开发 海拔科技