Redux 的基础概念-API

 

三个基本原则

  • 整个应用只有惟一一个可信数据源,也就是只有一个 Store
  • State 只能经过触发 Action 来更改
  • State 的更改必须写成纯函数,也就是每次更改老是返回一个新的 State,在 Redux 里这种函数称为 Reducer

Actions

Action 很简单,就是一个单纯的包含 { type, payload } 的对象,type 是一个常量用来标示动做类型,payload 是这个动做携带的数据。Action 须要经过 store.dispatch() 方法来发送。javascript

好比一个最简单的 action:java

{
  type: 'ADD_TODO', text: 'Build my first Redux app' } 

通常来讲,会使用函数(Action Creators)来生成 action,这样会有更大的灵活性,Action Creators 是一个pure function,它最后会返回一个 action 对象:git

function addTodo(text) { return { type: 'ADD_TODO', text } } 

因此如今要触发一个动做只要调用 dispatchdispatch(addTodo(text))github

稍后会讲到如何拿到 store.dispatchredux

Reducers

Reducer 用来处理 Action 触发的对状态树的更改。app

因此一个 reducer 函数会接受 oldState 和 action 两个参数,返回一个新的 state:(oldState, action) => newState。一个简单的 reducer 可能相似这样:dom

const initialState = { a: 'a', b: 'b' }; function someApp(state = initialState, action) { switch (action.type) { case 'CHANGE_A': return { ...state, a: 'Modified a' }; case 'CHANGE_B': return { ...state, b: action.payload }; default: return state } } 

值得注意的有两点:ecmascript

  • 咱们用到了 object spread 语法 确保不会更改到 oldState 而是返回一个 newState
  • 对于不须要处理的 action,直接返回 oldState

Reducer 也是 pure function,这点很是重要,因此绝对不要在 reducer 里面作一些引入 side-effects 的事情,好比:ide

  • 直接修改 state 参数对象
  • 请求 API
  • 调用不纯的函数,好比 Data.now() Math.random()

由于 Redux 里面只有一个 Store,对应一个 State 状态,因此整个 State 对象就是由一个 reducer 函数管理,可是若是全部的状态更改逻辑都放在这一个 reducer 里面,显然会变得愈来愈巨大,愈来愈难以维护。得益于纯函数的实现,咱们只须要稍微变通一下,让状态树上的每一个字段都有一个 reducer 函数来管理就能够拆分红很小的 reducer 了:函数

function someApp(state = {}, action) { return { a: reducerA(state.a, action), b: reducerB(state.b, action) }; } 

对于 reducerA 和 reducerB 来讲,他们依然是形如:(oldState, action) => newState 的函数,只是这时候的 state 不是整个状态树,而是树上的特定字段,每一个 reducer 只须要判断 action,管理本身关心的状态字段数据就行了。

Redux 提供了一个工具函数 combineReducers 来简化这种 reducer 合并:

import { combineReducers } from 'redux'; const someApp = combineReducers({ a: reducerA, b: reducerB }); 

若是 reducer 函数名字和字段名字相同,利用 ES6 的 Destructuring 能够进一步简化成:combineReducers({ a, b })

象 someApp 这种管理整个 State 的 reducer,能够称为 root reducer。

Store

如今有了 Action 和 Reducer,Store 的做用就是链接这二者,Store 的做用有这么几个:

  • Hold 住整个应用的 State 状态树
  • 提供一个 getState() 方法获取 State
  • 提供一个 dispatch() 方法发送 action 更改 State
  • 提供一个 subscribe() 方法注册回调函数监听 State 的更改

建立一个 Store 很容易,将 root reducer 函数传递给 createStore 方法便可:

import { createStore } from 'redux'; import someApp from './reducers'; let store = createStore(someApp); // 你也能够额外指定一个初始 State(initialState),这对于服务端渲染颇有用 // let store = createStore(someApp, window.STATE_FROM_SERVER); 

如今咱们就拿到了 store.dispatch,能够用来分发 action 了:

let unsubscribe = store.subscribe(() => console.log(store.getState())); // Dispatch store.dispatch({ type: 'CHANGE_A' }); store.dispatch({ type: 'CHANGE_B', payload: 'Modified b' }); // Stop listening to state updates unsubscribe(); 

Data Flow

以上提到的 store.dispatch(action) -> reducer(state, action) -> store.getState() 其实就构成了一个“单向数据流”,咱们再来总结一下。

1. 调用 store.dispatch(action)

Action 是一个包含 { type, payload } 的对象,它描述了“发生了什么”,好比:

{ type: 'LIKE_ARTICLE', articleID: 42 } { type: 'FETCH_USER_SUCCESS', response: { id: 3, name: 'Mary' } } { type: 'ADD_TODO', text: 'Read the Redux docs.' } 

你能够在任何地方调用 store.dispatch(action),好比组件内部,Ajax 回调函数里面等等。

2. Action 会触发给 Store 指定的 root reducer

root reducer 会返回一个完整的状态树,State 对象上的各个字段值能够由各自的 reducer 函数处理并返回新的值。

  • reducer 函数接受 (state, action) 两个参数
  • reducer 函数判断 action.type 而后处理对应的 action.payload 数据来更新并返回一个新的 state

3. Store 会保存 root reducer 返回的状态树

新的 State 会替代旧的 State,而后全部 store.subscribe(listener) 注册的回调函数会被调用,在回调函数里面能够经过 store.getState() 拿到新的 State。

+

 

这就是 Redux 的运做流程,接下来看如何在 React 里面使用 Redux。

相关文章
相关标签/搜索