在小程序的中,虽然有globalData这种全局唯一数据存储,但是每个page并不能感知globalData是否发生了变化继而去更新page的data。比如A页面改变了globalData,但是B页面并不能知道globalData改变了,B页面只能在onShow这个生命周期中去重新获取globalData,并setData
甚至在同一个页面中,我改变了globalData,但页面并不知道,必须手动去setData,这样页面中的数据才会重新渲染
于是我想是不是可以使用观察者模式,让globalData一改变,全部页面就更新数据呢 当然,这个只是一个思路,并没有考虑多次setData降低性能,你在看这篇博客时,可以当作是学习观察者模式,哈哈,当然,如果能点个赞最好了,谢谢
经评论区指正,改正了用词,感谢
观察者模式,有两个角色,一个是目标,一个是观察者。可以形象的比喻为老师和学生
老师在台上讲课(发布消息,触发事件),学生在台下听课(接受消息)然后吸收知识(执行任务) 如果老师觉得你在开小差,他会让你滚出教室(删除观察者)
老师觉得你反省的差不多了,他会让你进入教室(增加观察者)
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("我在听课") } } 复制代码
总结:
目标有三个能力:
- 增加观察者
- 删除观察者
- 通知观察者执行某一个任务
观察者有一个能力:
- 执行任务
小程序目录如下
在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: '前端攻城狮' } } }); 复制代码
新建四个页面
// 四个页面全部一样如下 // 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); }, 复制代码
先点击四个tabBar页面实现注册观察者,然后点击修改名字,会发现其他页面也更新了globalData并setData
具体代码在下面链接中:
作者:胡志武
时间:2020/03/26
如果有错漏处,请指正。看官们点个赞吧