Redux可是一个大名鼎鼎的库,很多地方都在用,我也用了几年了,今天这篇文章就是自己来实现一个Redux,以便于深入理解他的原理。我们还是老套路,从基本的用法入手,然后自己实现一个Redux来替代源码的NPM包,但是功能保持不变。本文只会实现Redux的核心库,跟其他库的配合使用,比如React-Redux准备后面单独写一篇文章来讲。有时候我们过于关注使用,只记住了各种使用方式,反而忽略了他们的核心原理,但是如果我们想真正的提高技术,最好还是一个一个搞清楚,比如Redux和React-Redux看起来很像,但是他们的核心理念和关注点是不同的,Redux其实只是一个单纯状态管理库,没有任何界面相关的东西,React-Redux关注的是怎么将Redux跟React结合起来,用到了一些React的API。
本文全部代码已经上传到GitHub,大家可以拿下来玩下:https://github.com/dennis-jiang/Front-End-Knowledges/tree/master/Examples/React/redux
基本概念 Redux的概念有很多文章都讲过,想必大家都看过很多了,我这里不再展开,只是简单提一下。Redux基本概念主要有以下几个:
Store 人如其名,Store就是一个仓库,它存储了所有的状态(State),还提供了一些操作他的API,我们后续的操作其实都是在操作这个仓库。假如我们的仓库是用来放牛奶的,初始情况下,我们的仓库里面一箱牛奶都没有,那Store的状态(State)就是:
{ milk: 0 } Actions 一个Action就是一个动作,这个动作的目的是更改Store中的某个状态,Store还是上面的那个仓库,现在我想往仓库放一箱牛奶,那"我想往仓库放一箱牛奶"就是一个Action,代码就是这样:
{ type: “PUT_MILK”, count: 1 } Reducers 前面"我想往仓库放一箱牛奶"只是想了,还没操作,具体操作要靠Reducer,Reducer就是根据接收的Action来改变Store中的状态,比如我接收了一个PUT_MILK,同时数量count是1,那放进去的结果就是milk增加了1,从0变成了1,代码就是这样:
const initState = { milk: 0 }
function reducer(state = initState, action) { switch (action.type) { case ‘PUT_MILK’: return {…state, milk: state.milk + action.count} default: return state } } 可以看到Redux本身就是一个单纯的状态机,Store存放了所有的状态,Action是一个改变状态的通知,Reducer接收到通知就更改Store中对应的状态。
简单例子 下面我们来看一个简单的例子,包含了前面提到的Store,Action和Reducer这几个概念:
import { createStore } from ‘redux’;
const initState = { milk: 0 };
function reducer(state = initState, action) { switch (action.type) { case ‘PUT_MILK’: return {…state, milk: state.milk + action.count}; case ‘TAKE_MILK’: return {…state, milk: state.milk - action.count}; default: return state; } }
let store = createStore(reducer);
// subscribe其实就是订阅store的变化,一旦store发生了变化,传入的回调函数就会被调用 // 如果是结合页面更新,更新的操作就是在这里执行 store.subscribe(() => console.log(store.getState()));
// 将action发出去要用dispatch store.dispatch({ type: ‘PUT_MILK’ }); // milk: 1 store.dispatch({ type: ‘PUT_MILK’ }); // milk: 2 store.dispatch({ type: ‘TAKE_MILK’ }); // milk: 1