在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ Redux 的基礎(chǔ)概念
React 組件
Redux 的基礎(chǔ)概念
JSX
DOM 操作
在 React 應(yīng)用中使用 Redux
進(jìn)化 Flux
Webpack 配置 React 開(kāi)發(fā)環(huán)境
服務(wù)器端渲染
組合組件
表單
屬性擴(kuò)散
開(kāi)發(fā)環(huán)境配置
組件生命周期
Data Flow
JSX 與 HTML 的差異
組件間通信
使用 JSX
事件處理
Flux
React 概覽
Mixins
Redux

Redux 的基礎(chǔ)概念

三個(gè)基本原則

  • 整個(gè)應(yīng)用只有唯一一個(gè)可信數(shù)據(jù)源,也就是只有一個(gè) Store
  • State 只能通過(guò)觸發(fā) Action 來(lái)更改
  • State 的更改必須寫(xiě)成純函數(shù),也就是每次更改總是返回一個(gè)新的 State,在 Redux 里這種函數(shù)稱(chēng)為 Reducer

Actions

Action 很簡(jiǎn)單,就是一個(gè)單純的包含 { type, payload } 的對(duì)象,type 是一個(gè)常量用來(lái)標(biāo)示動(dòng)作類(lèi)型,payload 是這個(gè)動(dòng)作攜帶的數(shù)據(jù)。Action 需要通過(guò) store.dispatch() 方法來(lái)發(fā)送。

比如一個(gè)最簡(jiǎn)單的 action:

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

一般來(lái)說(shuō),會(huì)使用函數(shù)(Action Creators)來(lái)生成 action,這樣會(huì)有更大的靈活性,Action Creators 是一個(gè) pure function,它最后會(huì)返回一個(gè) action 對(duì)象:

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

所以現(xiàn)在要觸發(fā)一個(gè)動(dòng)作只要調(diào)用 dispatch: dispatch(addTodo(text))

稍后會(huì)講到如何拿到 store.dispatch

Reducers

Reducer 用來(lái)處理 Action 觸發(fā)的對(duì)狀態(tài)樹(shù)的更改。

所以一個(gè) reducer 函數(shù)會(huì)接受 oldStateaction 兩個(gè)參數(shù),返回一個(gè)新的 state:(oldState, action) => newState。一個(gè)簡(jiǎn)單的 reducer 可能類(lèi)似這樣:

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
  }
}

值得注意的有兩點(diǎn):

  • 我們用到了 object spread 語(yǔ)法 確保不會(huì)更改到 oldState 而是返回一個(gè) newState
  • 對(duì)于不需要處理的 action,直接返回 oldState

Reducer 也是 pure function,這點(diǎn)非常重要,所以絕對(duì)不要在 reducer 里面做一些引入 side-effects 的事情,比如:

  • 直接修改 state 參數(shù)對(duì)象
  • 請(qǐng)求 API
  • 調(diào)用不純的函數(shù),比如 Data.now() Math.random()

因?yàn)?Redux 里面只有一個(gè) Store,對(duì)應(yīng)一個(gè) State 狀態(tài),所以整個(gè) State 對(duì)象就是由一個(gè) reducer 函數(shù)管理,但是如果所有的狀態(tài)更改邏輯都放在這一個(gè) reducer 里面,顯然會(huì)變得越來(lái)越巨大,越來(lái)越難以維護(hù)。得益于純函數(shù)的實(shí)現(xiàn),我們只需要稍微變通一下,讓狀態(tài)樹(shù)上的每個(gè)字段都有一個(gè) reducer 函數(shù)來(lái)管理就可以拆分成很小的 reducer 了:

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

對(duì)于 reducerAreducerB 來(lái)說(shuō),他們依然是形如:(oldState, action) => newState 的函數(shù),只是這時(shí)候的 state 不是整個(gè)狀態(tài)樹(shù),而是樹(shù)上的特定字段,每個(gè) reducer 只需要判斷 action,管理自己關(guān)心的狀態(tài)字段數(shù)據(jù)就好了。

Redux 提供了一個(gè)工具函數(shù) combineReducers 來(lái)簡(jiǎn)化這種 reducer 合并:

import { combineReducers } from 'redux';

const someApp = combineReducers({
  a: reducerA,
  b: reducerB
});

如果 reducer 函數(shù)名字和字段名字相同,利用 ES6 的 Destructuring 可以進(jìn)一步簡(jiǎn)化成:combineReducers({ a, b })

someApp 這種管理整個(gè) State 的 reducer,可以稱(chēng)為 root reducer

Store

現(xiàn)在有了 Action 和 Reducer,Store 的作用就是連接這兩者,Store 的作用有這么幾個(gè):

  • Hold 住整個(gè)應(yīng)用的 State 狀態(tài)樹(shù)
  • 提供一個(gè) getState() 方法獲取 State
  • 提供一個(gè) dispatch() 方法發(fā)送 action 更改 State
  • 提供一個(gè) subscribe() 方法注冊(cè)回調(diào)函數(shù)監(jiān)聽(tīng) State 的更改

創(chuàng)建一個(gè) Store 很容易,將 root reducer 函數(shù)傳遞給 createStore 方法即可:

import { createStore } from 'redux';
import someApp from './reducers';
let store = createStore(someApp);

// 你也可以額外指定一個(gè)初始 State(initialState),這對(duì)于服務(wù)端渲染很有用
// let store = createStore(someApp, window.STATE_FROM_SERVER);

現(xiàn)在我們就拿到了 store.dispatch,可以用來(lái)分發(fā) 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() 其實(shí)就構(gòu)成了一個(gè)“單向數(shù)據(jù)流”,我們?cè)賮?lái)總結(jié)一下。

1. 調(diào)用 store.dispatch(action)

Action 是一個(gè)包含 { type, payload } 的對(duì)象,它描述了“發(fā)生了什么”,比如:

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

你可以在任何地方調(diào)用 store.dispatch(action),比如組件內(nèi)部,Ajax 回調(diào)函數(shù)里面等等。

2. Action 會(huì)觸發(fā)給 Store 指定的 root reducer

root reducer 會(huì)返回一個(gè)完整的狀態(tài)樹(shù),State 對(duì)象上的各個(gè)字段值可以由各自的 reducer 函數(shù)處理并返回新的值。

  • reducer 函數(shù)接受 (state, action) 兩個(gè)參數(shù)
  • reducer 函數(shù)判斷 action.type 然后處理對(duì)應(yīng)的 action.payload 數(shù)據(jù)來(lái)更新并返回一個(gè)新的 state

3. Store 會(huì)保存 root reducer 返回的狀態(tài)樹(shù)

新的 State 會(huì)替代舊的 State,然后所有 store.subscribe(listener) 注冊(cè)的回調(diào)函數(shù)會(huì)被調(diào)用,在回調(diào)函數(shù)里面可以通過(guò) store.getState() 拿到新的 State。

這就是 Redux 的運(yùn)作流程,接下來(lái)看如何在 React 里面使用 Redux。

上一篇:DOM 操作下一篇:Mixins