零、Redux的三大原则
1 单一数据源【整个应用的状态state只存在于一个 对象树中,而对象树 存在与 唯一一个store中】
2 state只是只读的【要想改变state就必须通过 派发acttion, 然后由reducer去处理并返回新的状态。】!!
3 由纯函数来执行修改【需要自己去编写reducer。 dispatch(action) 之后会 “走reducer的函数流程”】
一、我们需要大致实现的功能点(让我们来看下redux store暴漏的api)
1 store 内部有 state【一般存放整个应用的全部状态】、listeners【存放各种监听方法的一个数组】 和 各种方法【getState、dispatch、subscribe】
const store = {
state: {}, // 全局唯一的state,内部变量,通过getState()获取
listeners: [], // listeners,用来诸如视图更新的操作
getState: () => {}, // 获取state
dispatch: () => {}, // 分发action
subscribe: () => {}, // 用来订阅state变化
}
二、createStore【很核心!!用于生成、返回一个 store。2属性(state、listeners)和 3方法(getState、dispatch、subscribe)】
createStore是用来初始化redux store的,是redux最重要的api。
const createStore = (reducer, initState) => {
const store = {}; // 从 createStore方法中 返回含有各种属性、方法的 store
store.state = initState; // store的默认状态
store.listeners = []; // "监听器", 结合 暴露出来的 subscribe方法 使用。 每次 subscribe 都会将某方法塞进 listneers数组中,
// 每次 dispatch 就执行一遍 listeners 数组中的所有方法。
store.getState = () => store.state;
// 动作 派发dispatch 出去后,由 "传进来的 reducer方法" 去处理,在不改变愿状态下 返回一个新状态 —— 纯函数!!
// dispatch派发动作求得新状态后, 别忘了把 listeners数组里面监听的方法 执行一遍。
store.dispatch = (action) => {
store.state = reducer(store.state, action);
store.listeners.forEach(listener => listener());
};
store.subscribe = (listener) => {
store.listeners.push(listener);
}
return store; // 想象 createStore 就是专门用来 造store的, "应该算得上是一个单例的方法"
};
三、实现reducer并测试
// reducer 本质是一个函数,可以通过 combinexxx 将多个 reducer合并成 一个store【保证store的 "唯一性"】 !!
function counter(state=0, action) {
// 注意!! reducer 应该是一个 纯函数,不要再 reduxer中改变 store中的 state !!
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
// 通过向 createStore 方法传入 reducer ,来创建 store实例
let store = createStore(counter);
// 进行 "状态变化的监听"
store.subscribe(() =>
console.log(store.getState())
);
// 进行 action的派发
store.dispatch({ type: 'INCREMENT' })
// 1
store.dispatch({ type: 'INCREMENT' })
// 2
store.dispatch({ type: 'DECREMENT' })
// 1