使用观察者模式+globalData实现小程序全局实时状态管理

2020/3/27 11:07:31

本文主要是介绍使用观察者模式+globalData实现小程序全局实时状态管理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

前言

在小程序的中,虽然有globalData这种全局唯一数据存储,但是每个page并不能感知globalData是否发生了变化继而去更新page的data。比如A页面改变了globalData,但是B页面并不能知道globalData改变了,B页面只能在onShow这个生命周期中去重新获取globalData,并setData

甚至在同一个页面中,我改变了globalData,但页面并不知道,必须手动去setData,这样页面中的数据才会重新渲染

于是我想是不是可以使用观察者模式,让globalData一改变,全部页面就更新数据呢 当然,这个只是一个思路,并没有考虑多次setData降低性能,你在看这篇博客时,可以当作是学习观察者模式,哈哈,当然,如果能点个赞最好了,谢谢

什么是观察者模式?

经评论区指正,改正了用词,感谢

one

观察者模式,有两个角色,一个是目标,一个是观察者。可以形象的比喻为老师和学生

老师在台上讲课(发布消息,触发事件),学生在台下听课(接受消息)然后吸收知识(执行任务) 如果老师觉得你在开小差,他会让你滚出教室(删除观察者)

老师觉得你反省的差不多了,他会让你进入教室(增加观察者)

class Teacher{
  constructor(){
    this.students=[];//用来存储学生,即是存储观察者
  }
  add(student){
		this.students.push(studnet)
  }
  remove(student){
    this.students.forEach((item,index)=>{
      if(item==studnet){
        this.students.splice(index,1)
        return;
      }
    })
  }
  say(){//老师讲课
    this.students.forEach(item=>{
      item.listen()//要求学生们听课
    })
  }
}
class Student{
  listen(){
    console.log("我在听课")
  }
}
复制代码

总结:

目标有三个能力:

  1. 增加观察者
  2. 删除观察者
  3. 通知观察者执行某一个任务

观察者有一个能力:

  1. 执行任务

在小程序中使用观察者模式

小程序目录如下

image-20200326133153437

在publisher.js中

class Publisher {//发布者
  constructor() {
    this.observers = [];//存储观察者
  }
  add(observer) {//增加观察者
    this.observers.push(observer);
  }
  remove(observer) {//删除观察者
    this.observers.forEach((item, index) => {
      if (item == observer) {
        this.observers.splice(index, 1);
        return;
      }
    });
  }
  notify() {// 向观察者发布消息
    this.observers.forEach(item => {
      item.update();//  在每一个页面中创建一个update函数用来更新globalData并渲染
    });
  }
}
// 这个类继承Publisher并监听globalData的变化
class GlobalDataPublisher extends Publisher {
  constructor(globalData) {
    super();
    this.globalData = globalData;
    this.observers = [];
  }
  getGlobalData() {
    return this.globalData;
  }
  setGlobalData(globalData) {// globalData一旦变化,就通知观察者
    this.globalData = globalData;
    this.notify();
  }
}
module.exports = {
  Publisher,
  GlobalDataPublisher
};

复制代码

app.js

//app.js
var { GlobalDataPublisher } = require('./utils/publisher');
App({
  onLaunch: function() {
    // 将这个类挂载到全局唯一实例的App上
    this.globalDataPublisher = new GlobalDataPublisher(this.globalData);
  },
  globalData: {
    userInfo: {
      name: '胡志武',
      age: 18,
      job: '前端攻城狮'
    }
  }
});

复制代码

新建四个页面

image-20200326133711366

// 四个页面全部一样如下
// wxml
 <view>
    <text>name:{{userInfo.name}}</text>
    <text>age:{{userInfo.age}}</text>
    <text>job:{{userInfo.job}}</text>
</view>
<view bindtap="changeName">改名字为前端小学生</view>
<view bindtap="changeJob">改职位为前端打杂</view>
复制代码
// js
// 这是每个页面需要执行的任务,获取globalData并setData,实现页面及时渲染
update() {
  	console.log("user页面更新")
    const app = getApp();
    const globalData = app.globalDataPublisher.getGlobalData();
    this.globalData = globalData;
    this.setData({
      ...globalData
    });
  },
复制代码
//j s
// 每个页面onLoad时。需要增加观察者,
onLoad: function(options) {
    const app = getApp();
    app.globalDataPublisher.add(this);// 增加观察者
    this.globalDataPublisher = app.globalDataPublisher;
    this.globalData = app.globalDataPublisher.getGlobalData();
    this.setData({
      ...this.globalData
    });
  },
复制代码
// js 业务功能
// 用来检查是不是全局实时更新
changeName() {
  	console.log("user页面更新,changeName")
    this.globalData.userInfo.name = '前端小学生';
    this.globalDataPublisher.setGlobalData(this.globalData);
  },
  changeJob() {
    console.log("user页面更新,changeJob")
    this.globalData.userInfo.job = '前端打杂';
    this.globalDataPublisher.setGlobalData(this.globalData);
  },
复制代码

a901b08c-1a46-453c-b463-d20c7fc86008

先点击四个tabBar页面实现注册观察者,然后点击修改名字,会发现其他页面也更新了globalData并setData

具体代码在下面链接中:

github.com/huzhiwu1/gl…

结语

作者:胡志武

时间:2020/03/26

如果有错漏处,请指正。看官们点个赞吧



这篇关于使用观察者模式+globalData实现小程序全局实时状态管理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程