Introduction: This article mainly introduces in the small program, how to keep data synchronization between multiple pages

In many products, there is a need for data synchronization across pages, as shown in the following example:

To better understand this scenario, let’s describe it in detail:

  1. This scenario consists of four pages:Dynamic square,Personal center,My dynamic,Dynamic details
  2. First, enterDynamic squarePage, request to load data, display dynamic list, in which, we use green inner shadow to distinguish the dynamic is “mine”, other unshaded representation is “others”;
  3. Then, enterPersonal centerPage, request to load data, show the number of likes;
  4. Click my feed to enterMy dynamicPage, request to load data, display my dynamic list;
  5. Click one of the dynamic, enterDynamic detailsPage, request to load data, proceedgive a likeOperation;
  6. In step 5, after a successful like, go back toMy dynamicPage, you can see this dynamicStatus and number of likesHas changed, has synchronized;
  7. Back to thePersonal centerPage can also be seenA great number ofHas changed, has synchronized;
  8. Go back toDynamic squarePage, you can also see a corresponding dynamicStatus and number of likesHas changed, has synchronized;

Now let’s discuss the implementation of this scene. Before that, we should first understand the status and relationship of each page in this scene when it is liked.

As you can see in the image above, all four pages are already open when we like them (four WebViews). When we “like” successfully, click on the upper left to return, the webView of the dynamic details page will be closed, and we will directly see the next webview, that is, my dynamic page, which already exists. The same goes for other pages.

So how do we synchronize updates to existing pages?

Of course, if you are a little lazy, you can just pull the data render page again during onShow. But this is obviously very low grade, undesirable and unnecessary. It takes time to re-pull the data, the page is re-rendered and there is a splash screen, but the point is there is no need to re-pull the data because the data has changed and the front end knows about it.

So what we can do is, when the dynamic details page is liked, save a data to the global globalData, go back to my dynamic page, check onShow to see if there are any likes in the global globalData, if there are, read and update the corresponding dynamic.

// dynamic detail page js
onLike() {
  ...
  success: (a)= > {
    App.globalData.like = {
      fid: 10001.likes: 1.hasLike: true}}}// My dynamic page js
onShow() {
  if(App.globalData.like ! = =null) {
    // Read globalData. like data to update
    this.doUpdata()
    // It is important to note that after the update, you need to clear globaldata.like, otherwise the next onShow will continue to use this logic
    App.globalData.like = null}}Copy the code

This seems to work for our purposes, with no requests, pure front-end local updates.

However, there is a problem with this. When we go back to the personal center page, we need to check whether the number of likes needs to be updated, and when we go back to the dynamic Square page, we also need to check whether the likes have changed. However, when onShow tries to determine app.globaldata. like on both pages, it can’t be detected because the data is null in my dynamic page onShow.

Generally speaking, when a “like” is clicked, only one piece of data is produced, but there are multiple consumers. Whichever page consumes the data first, the other pages cannot detect the data.

From there, we thought we’d use EventBus.

First, we implemented a simple Set of EventBus ourselves.

Source: see git.weixin.qq.com/xinyuanliu/…

Initialize EventBus when the applet starts:

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)
  },
  ...
}
Copy the code

Each page registers a listening event when onLoad (in this case, my dynamic page) :

// my dynamic.js
const App = getApp()

Page({
  data: {
    list: []},onLoad: function (options) {...// Listen for the likes event broadcast↓ app.events.on ('feedsLike', data => {
      console.log('My dynamic page received a thumbs-up notification:', data)
      // Perform the update operation
    })
    // Listen to publish event broadcasts↓ app.events.on ('publishFeeds', data => {
      console.log('My dynamic page received a release dynamic notification:', data)
      // Perform the update operation})},... })Copy the code

Then send event notification when dynamic like. (Here a dynamic is encapsulated as a component, does not belong to a page, the like event is also encapsulated in the component)

const App = getApp()

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

      likes += (hasLike && - 1 || 1) hasLike = ! hasLikethis.updateFeeds(likes, hasLike).then((a)= > {
        this.setData({
          likes,
          hasLike
        })

        // Broadcast events↓ app. emitFeedsLike({uid: this.data.uid,
          fid: this.data.fid, likes, hasLike }) }) }, ... }})Copy the code

In this way, we have implemented a cross-page data synchronization scheme in the applet.

Intuitively this is perfect for our needs. But there is one area in the mini-program that is not quite consistent with our normal experience. When the page is closed, its objects are not destroyed, because the logic layer of the applet is shared by the same process.

Therefore, a listening event is registered every time you enter the page, and it is not destroyed when you exit the page. That way, repeating the page multiple times registers multiple duplicate events, and when the event occurs, multiple responses are executed. Please look carefully at the picture below!

To avoid this, it is important to actively destroy listening events in the onUnload event of the page.

Page({
  eventsListener: {},
  data: {
    list: []},onLoad: function (options) {...// Listen for the likes event broadcast↓ ↓this.eventsListener.feedsLike = App.events.on('feedsLike', data => {
      console.log('My dynamic page received a thumbs-up notification:', data)
      // Perform the update operation
    })
    // Listen to publish event broadcasts↓ ↓this.eventsListener.publishFeeds= App.events.on('publishFeeds', data => {
      console.log('My dynamic page received a release dynamic notification:', data)
      // Perform the update operation})}, ↓ onUnload() {for (let i in this.eventsListener) {
      App.events.remove(i, this.eventsListener[i])
    } 
  },
  ...
})
Copy the code

So far, we have achieved perfect cross-page/component, multi-page data synchronization in the small program.

In this paper, we study the demo can experience in the small program, the project source code: git.weixin.qq.com/xinyuanliu/…

Welcome exchange and discussion.


It’s time for a commercial break

Not enough? Learn how to use React Hooks to reconfigure your small programs. Learn how to use React Hooks to reconfigure your small programs. Learn how to use React Hooks to reconfigure your small programs. Scan the QR code below for details.