实现一个简单的Redux
状态管理是当前前端框架开发当中一个很重要的点当业务或者系统复杂时,状态管理能让我们更加清晰地了解数据的流动
本文通过实现一个简单的Redux来阐述一个状态管理库的思想
什么是状态管理,我们为什么需要状态管理
目前前端开发框架盛行,在框架的使用过程中就会遇到一个问题:组件间的数据通信如何来做。简单是父子组件我们可以通过props
来实现数据通信,当组件层级变深,仅靠props
就不足够支撑我们的需求,一个全局的状态管理也就变为一个迫切的需求。
Redux的思想
- Store
Redux只有一个Store,Store不能直接进行修改,每次操作之后都是返回一个新的对象
Action
Action就是View发出的通知,告诉Store 数据要改变,Action通过特定的type来知晓做何种操作
const action = { type: 'plus', data: {} };
- Reducer
Reducer是一个纯函数,接受action和state,然后返回一个新的state。
总结一下,Redux的流程如下:
// View 发出 Action
store.dispatch(action);
// store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action。 Reducer 会返回新的 State
let nextState = xxxReducer(previousState, action);
// State 一旦有变化,Store 就会调用监听函数
store.subscribe(listener);
// listener中可以修改组件的状态,重新渲染组件
function listerner() {
let newState = store.getState();
component.setState(newState);
}
实现一个简单的Redux
状态管理,说到底就是将需要共享的数据存放在一个公共的地方,所有组件都通过它来进行数据的操作。自然而然的,我们可以想到创建一个全局的对象来存放数据,所以先创建一个state.js
文件
// state.js
export const state = {
count: 0,
}
有了数据,我们就需要有数据的存取,以及发布订阅事件
因此有了以下的store.js
文件
// store.js
import { state } from './state.js';
export const createStore = (reducer) => {
let currentState = state; // state
function getState() { // 获取state
return currentState;
}
function dispatch() { // 设置state
}
function subscribe() { // 订阅事件
}
return { getState, dispatch, subscribe };
}
在这里其实用到了闭包的思想
其中getState
很简单,就是获取当前的state
值
dispatch
状态管理库的一个原则是不能随便修改状态的值,需要做到有条理,有标记地修改。我们将操作单独封装在reducer.js
中,以此来保持store.js
的纯净
// reducer.js
import { state as initialState } from './state.js';
export function reducer(state = initialState, action) {
switch(action.type) {
case 'plus':
return {
...state,
count: state.count + 1
};
break;
case 'subtract':
return {
...state,
count: state.count - 1
}
break;
default:
return initialState;
}
}
然后在store.js
中进行使用
// store.js
import { state } from './state.js';
export const createStore = (reducer) => {
let currentState = state; // state
function getState() { // 获取state
return currentState;
}
function dispatch(action) { // 设置state
currentState = reducer(currentState, action);
}
function subscribe() { // 订阅事件
}
return { getState, dispatch, subscribe };
}
状态管理库的另一个能力就是能够通过数据改变引起视图的改变。我们通过发布订阅模式,就能实现这一效果,通过subscribe()
来订阅事件,在dispatch()
的时候触发订阅的消息。当然真正的状态管理库中这一块肯定是很复杂的,我们这里只是简单地写个示例。
我们通过一个数组来存放监听的事件,通过subscribe
来添加事件
// store.js
import { state } from './state.js';
export const createStore = (reducer) => {
let currentState = state; // state
let queue = [];
function getState() { // 获取state
return currentState;
}
function dispatch(action) { // 设置state
currentState = reducer(currentState, action);
queue.forEach(fn => {
fn();
})
}
function subscribe(fn) { // 订阅事件
queue.push(fn);
}
return { getState, dispatch, subscribe };
}
之后添加测试用例来进行测试
import 'createStore' from './store';
const store = createStore(reducer);
store.subscribe(() => { console.log('component 1') });
store.subscribe(() => { console.log('component 2') });
store.dispatch({ type: 'plus' });
store.dispatch({ type: 'plus' });
console.log(store.getState());
// component 1
// component 2
// component 1
// component 2
// { count: 2 }
这就是一个简单的Redux
的思想。