前言
随着 JavaScript 单页应用开发日趋复杂,JavaScript 需要管理比任何时候都要多的 state (状态)
Flow
redux的工作流大致如下组件想要获取State, 发出一个Action,创建了一个请求交给Store,Store借助Reducer确认了该State的状态,Reducer返回给Store一个结果,Store再把这个State转给组件。
三大原则
单一数据源
整个应用的state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
State 是只读的
唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
使用纯函数来执行修改
为了描述 action 如何改变 state tree ,你需要编写 reducers,reducer 只是一些纯函数,它接收先前的 state 和 action,并返回新的 state。
Action
Action 是把数据从应用传到 store 的有效载体。它是 store 数据的唯一来源。一般来说会通过 store.dispatch()将 action 传到 store,一般会定义:
const ADD = 'add';
const SUB = 'sub';
{
type: ADD,
text: 'add 1'
}
{
id:1
type: SUB,
text: 'sub 1'
}
Action就是一个普通的js对象,可以定义成任何一种模式,type可以指定他的用途或者状态
Reduce
Reducers 指定了应用状态的变化如何响应action并发送到 store 的,记住 actions只是描述了有事情发生了这一事实,并没有描述应用如何更新 state,Reduce只是一个纯函数
const initState = {counter:1};
const reducer = function(state = initState, action) {
switch(action.type) {
case 'ADD':
return { ...state,counter: state.counter+1};
case 'SUB':
return {...state,counter: state.counter-1};
default:
return state;
}
};
Store
action是来描述“发生了什么”,reducer是来根据 action 更新 state 的用法。
Store 就是把它们联系到一起的对象。Store 有以下职责:
- 维持应用的 state;
- 提供getState()方法获取 state;
- 提供dispatch(action)方法更新 state;
- 通过 subscribe(listener)注册监听器 ,返回一个移除监听函数;
// 创建一个store方法 如下,第三个参数是middleWare
const createStore = function(reducer, preloadedState ,enhancer){
let currentState = preloadedState || undefined;
let listeners = [];
const getState = () => currentState;
const subscribe = (fn) => {
listeners.push(fn);
return () => { //返回一个移除方法
let index = listeners.indexOf(fn)
listeners.splice(index, 1)
}
};
const dispatch = (action) =>{
currentState = reducer(currentState, action);
listeners.forEach((item) => {
item();
});
}
return {
getState,
subscribe,
dispatch,
}
};
调用
let store = createStore(reducer);
store.subscribe(function(){
console.log('before1')
});
store.subscribe(function() {
console.log('before2')
});
store.dispatch({
type:'ADD'
});
console.log(store.getState());
store.dispatch({
type: 'ADD'
});
console.log(store.getState());
store.dispatch({
type: 'SUB'
});
console.log(store.getState());
before1
before2
{ counter: 2 }
before1
before2
{ counter: 3 }
before1
before2
{ counter: 2 }