回顾
https://blog.csdn.net/tuzi007a/article/details/129645629
Redux
上篇已经实现了状态的获取和更新,如何实现状态更新后通知用到该状态的组件去更新为最新状态呢?这里使用了最基础的观察者模式。我们先来简单看下观察者模式
// 观察者
class Observer {
constructor(fn) {
this.update = fn;
}
}
// 被观察者
class Subject {
constructor() {
this.observers = [];
}
addObserver(observer) {
this.observers.push(observer);
}
notify() {
this.observers.forEach(observer => {
observer.update();
})
}
}
const subject = new Subject();
const update1 = () => {console.log('boserver1 数据更新了')};
const update2 = () => {console.log('boserver2 数据更新了')};
const observer1 = new Observer(update1);
const observer2 = new Observer(update2);
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notify()
观察者在监听时,定义了一个回调函数,被观察者把观察者们加入观察者列表,在数据更新时, 执行notify
通知观察者们,调用它们的回调函数update
。总而言之,被观察者需要准备一个回调函数,想要监听数据时,就把自己的回调函数添加到观察者列表里。观察者准备一个观察者列表,在通知时,执行观察者的回调函数即可。如果想要取消监听,只需要把该观察者在观察者列表的回调函数删除即可。现在我们来实现一下
const createStore = (reducer) => {
let currentState = {};
// 存储观察者,我们用Map储存,方便在取消监听的时候进行删除操作
const listeners = new Map();
// 准备一个序列号,方便对观察者操作
let listenerCount = 0;
function getState() {
return currentState;
}
function dispatch(action) {
currentState = reducer(currentState, action);
// 更新状态时,及时执行回调,通知观察者
listeners.forEach(listener => listener());
}
function subscribe(listener) {
// 每添加一个监听者,序列号就自增1
// listenerCount也是被闭包存储的变量
// 所以它会一直增加,不用担心序列号重复的问题
const listenerId = listenerCount++;
listeners.set(listenerId, listener);
// 返回一个取消监听的函数
return function unsubscirbe () {
listeners.delete(listenerId);
}
}
dispatch({ type: '@@REDUX__INIT' });
return { getState, dispatch, subscribe };
}
我们来测试一下
// src/index.js
console.log('store1: ', store.getState());
store.subscribe(() => {
console.log('数据更新了:', store.getState());
})
store.dispatch({ type: 'increament' }); // 增加
store.dispatch({ type: 'increament' }); // 增加
store.dispatch({ type: 'decreament' }); // 减少
这样就实现了状态的监听,及时更新数据。另外,还需要验证一下取消监听是否有效,再写个例子
console.log('store1: ', store.getState());
const unsubscribe = store.subscribe(() => {
console.log('数据更新了:', store.getState());
})
store.dispatch({ type: 'increament' }); // 增加
store.dispatch({ type: 'increament' }); // 增加
store.dispatch({ type: 'decreament' }); // 减少
unsubscribe(); // 取消监听
store.dispatch({ type: 'increament' }); // 增加
store.dispatch({ type: 'increament' }); // 增加
可以看到,在取消监听后的两次增加行为,并没有进行通知,取消监听是有效的。这样也验证了取消监听的功能。