Redux详解
Opened this issue · 0 comments
Redux是什么:
Redux是JavaScript的状态容器,为JavaScript应用提供可预测化的状态管理。
这句话包含以下几点涵义:
-
状态容器: 整个应用的 state 被储存在一棵 Object Tree 中,而且这个Object Tree 只存在于唯一一个 store 中。store是应用程序领域(app domain)的状态集合,一个应用程序只有一个store(Flux中允许有多个Store)。
-
JavaScript应用: Redux并不是只服务于react应用,是独立的一个库,可用于各种JavaScript应用。
-
可预测化: 可预测的(predictable): 因为Redux用了reducer与纯函数(pure function)的概念,每个新的state都会由旧的state建来一个全新的state,所有的状态修改都是"可预测的"。
Redux要解决的问题是什么:
JavaScript 单页应用开发越来越复杂,JavaScript 需要管理更多的状态(state)。这些状态可能是接口数据、缓存数据、mock数据、UI状态等。随着应用的变得复杂,而且随着代码量越来越大,管理不断变化的state非常困难。如果一个UI的改变,会引起一个model或者多个model的改变。亦或者一个model的改变引起另一个model或者多个model的改变时。当需要增加一个功能的时候,我们很难追踪到底发生了什么。系统会变得很难维护。Redux的出现就是为了解决 state 里的数据问题。
Redux让每个 state 变化都是可预测的,将应用中所有的动作与状态都统一管理,让一切有据可循。
Redux核心设计理念
Redux有三大原则
- 单一数据源: 整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
- state 是只读的,唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
- 使用纯函数来执行修改,为了描述 action 如何改变 state tree ,你需要编写 Reducer。Reducer 只是一些纯函数,它接收先前的 state 和 action,并返回新的 state。
Redux认为:
1. Web应用是一个状态机,视图与状态是一一对应的。
2. 所有的状态,保存在一个对象里面。
Redux介绍
Action
Action是通知,一般由View发出,告知Store应该发生变化。Action是一个对象,其中type属性是必须的,可以附带一些负载属性。
const action = {
type: 'ADD_USER',
name: '尖冰'
};
Reducer
Store收到 Action后,必须计算出一个新的State,这个计算过程称为Reducer 。 Reducer是一个函数,接受Action和当前状态作为参数,返回一个新的State。
const reducer = (state = 0, action) => {
switch (action.type) {
case 'ADD_USER':
return [action.name, ...state];
default:
return state;
}
};
const state = createStore(reducer);
Reducer是一个纯函数,即只要拥有相同的输入,必得到相同的输出 .
不要在Reducer中做以下操作:
- 修改传入参数
- 执行有副作用的操作,如 API 请求和路由跳转
- 调用非纯函数,如 Date.now() 或 Math.random()
combineReducers
一个应用可能包含有多个Reducer,每个Reducer只负责处理它管理的那部分State,那么最后多个Reducer怎么合并为一个reducers呢?Redux提供了combineReducers这个方法。该方法会将多个Reducer合并为一个reducers。
/**
* 添加用户 reducer
* @param {*} state
* @param {*} action
*/
let addUser = (state = [], action) => {
switch (action.type) {
case 'ADD_USER':
return [action.name, ...state];
default:
return state;
}
}
/**
* 编辑用户 reducer
* @param {*} state
* @param {*} action
*/
let editUser = (state = {}, action) => state;
/**
* 合并为一个 reducer
* @param {*} state
* @param {*} action
*/
let reducers = combineReducers({addUser, editUser});
Store
Store负责联系action和reducer,一个应用只能有一个Store。
Store有以下职责:
- 维持应用的 state;
- 提供 getState() 方法获取 state;
- 提供 dispatch(action) 方法更新 state;
- 通过 subscribe(listener) 注册监听器;
- 通过 subscribe(listener) 返回的函数注销监听器。
import { createStore } from 'redux'
const store = createStore(reducer);
store.subscribe(render);
store.dispatch({
type: 'ADD_USER',
name: '尖冰'
})
Store方法
Store = {
dispatch: Dispatch // 发送 action 时使用
getState: () => State // 获取当前 state
subscribe: (listener: () => void) => () => void // 注册回调,state有更动时调用
replaceReducer: (reducer: Reducer) => void //动态加载其它的reducer
}
Redux使用步骤
- 从redux模块中汇入createStore方法
import { createStore } from 'redux'
- 写一个reducer
function addUser(state = [], action) {
switch (action.type) {
case 'ADD_USER':
return [action.name, ...state];
default:
return state;
}
}
- 由写好的reducer,创建出 store
const store = createStore(reducer);
- render方法,如果有状态改变,重新render
function render() {
const data = store.getState();
data.map(() => {
...
});
}
- 首次调用 render
render();
- 订阅 render 函数到 store , store.subscribe(render)
store.subscribe(render);
- 触发事件调用store.dispatch(action)
store.dispatch({
type: 'ADD_USER',
name: '尖冰'
})
工作流程总结
第一步,发出Action
store.dispatch(action);
第二步,Store 自动调用 Reducer,并且传入两个参数,旧的Store以及Action.
let nextStare = addUser(previousState, action);
第三步,State发生变化,Store 就会调用注册函数
store.subscribe(listener);
第四步,listener可以通过store.getState()得到当前状态。调用render重新渲染。