一、什麼是redux?
一個組件裏可能會有不少的狀態,好比控制某個內容顯示的flag,從後端獲取的展現數據,那麼這些狀態能夠在本身的單個頁面進行管理,也能夠選擇別的管理方式,redux就是是一種狀態管理的方式。npm
二、爲何要用redux?
(1) 數據共享,當咱們的不少頁面都要用到同一數據時,就能夠把數據放到redux中,達到狀態共享的目的。
(2) 合併管理狀態,業務當中可能會有不少的狀態須要維護,且各個狀態之間可能還有相互依賴的關係,不統一管理的話很難追蹤狀態的變化。redux
三、redux的基礎概念
(1) store
store是一個倉庫,用來存儲數據,它能夠獲取數據,也能夠派發數據,還能監聽到數據的變化。後端
(2) action
action理解爲動做,action的值通常爲一個對象,格式如 { type: "", data: "" },type是必需要的,由於reducer處理數據的時候要根據不一樣的type來進行不一樣的操做。網絡
(3) reducer
reducer是初始化以及處理派發的action的純函數。app
四、如何使用redux?
首先安裝redux的依賴,npm i redux -D
(1) 定義action異步
export const countAction = (num) => ({ type: "ADD_NUMBER",data: num })
(2) 定義處理的action的reducer函數
export function counterReducer(prevState = 0, action){ switch(action.type){ case 'ADD_NUMBER': return prevState + num; default return prevState; } }
(3) 建立storefetch
import { createStore } from 'redux' import { counterReducer } from './counterReducer' export const store = createStore(counterReducer)
到這裏,store就建立完成了,在組件裏能夠直接引入store和action,進行派發action的操做,此時有一個Home的組件,咱們要在這裏更改state中的數據。spa
import { store } from './store' import { countAction } from './countAction' store.dispatch(countAction(5)) store.getState() // 5
五、redux的三大核心
(1) 單一數據源
當咱們有多個數據須要放到redux中管理時,是放在一個對象裏,這個對象放在store中管理,雖然redux並無強制只能建立一個store,可是多個數據源的話不那麼容易管理,單一的數據源能夠更好的追蹤狀態的變化。code
(2) state是隻讀的
想要改變state,沒法在組件上直接手動修改state的值,這樣能夠保證狀態不會被隨意改變,惟一的方式就是派發action,而是經過集中管理的形式去改變state。
(3) reducer是純函數
純函數指的是有相同的輸入一定有相同的輸出,在這種狀況下,不能夠修改入參,也不能發送網絡請求,也不能進行獲取隨機數這樣的操做,經過reducer將上一個state的狀態和當前派發的action鏈接起來,返回一個新的狀態。
六、redux如何進行異步操做?
redux中派發的action默認是隻能進行同步的操做的,action被規定爲一個對象,那若是想要在redux中進行異步操做,好比發送網絡請求該怎麼作?
這個時候須要用到中間件,經常使用的中間件有redux-thunk和redux-saga,須要安裝依賴 npm i redux-thunk -D/ npm i redux-sage -D
redux-thunk容許派發的action爲一個函數,能夠在這個函數中進行異步請求,請求執行完成以後再派發一個同步的action,用於修改store中的數據。
redux-saga派發的action仍然爲一個對象,可是saga在外側攔截action,使用生成器函數來監聽action,當派發的action中的type爲監聽的type時,再進行網絡請求的發送,以及改變store中的數據。
這裏演示一下redux-thunk,在定義store時,須要將中間件傳入
import { createStore, applyMiddleware } from 'redux' import { counterReducer } from './counterReducer' import thunk from 'redux-thunk' export const store = createStore(counterReducer,applyMiddleware(thunk))
action就能夠寫成函數的形式了
import { countAction } from './countAction' export const getInfo = (data) => { return (dispatch) => { // 執行異步操做,異步操做執行完成後,再派發一個同步的action // 這裏用fetch作一個演示,發送網絡請求後,更改以前的count的值 fetch('/') .then(xhr=>xhr.text()) .then(result=>dispatch(countAction(10))) } }
七、拆分reducer
當reducer須要處理的邏輯比較多時,一個reducer須要進行很是多的switch case的判斷,其中有獲取異步請求數據的、有全局保存的狀態,這時候邏輯就會比較雜亂,此時能夠將reducer拆分,而後再進行合併。
假設此時有兩個reducer,分別爲 countReducer、userInfoReducer,分別的狀態保存在store的countInfo和userInfo,此時可使用 combineReducer 這個方法來合併
import countReducer from './countReducer ' import userInfoReducer from './userInfoReducer' import { combineReducers } from 'redux' const reducer = combineReducers({ countInfo: countReducer, userInfo: userInfoReducer }) export default reducer
此時返回的reducer仍然是一個純函數,combineReducer這個函數就是依次執行傳入的reducers,若是store裏儲存的值發生了變化,就返回新的state,若是沒有變化,就返回原來的state。