我以我公司的項目為例子嘉竟,講一下我對redux的理解罚缕,如下圖所示:大家可以先看下第五塊-工作流程古拴,然后在從前面往后看诉位,理解會更深刻慕购,
希望對大家有幫助页屠!
image.png
一希停、前言
隨著WEB應(yīng)用變得越來越復(fù)雜仅乓,再加上node前后端分離越來越流行一也,那么對數(shù)據(jù)流動的控制就顯得越發(fā)重要巢寡。redux是在flux的基礎(chǔ)上產(chǎn)生的,
基本思想是保證數(shù)據(jù)的單向流動塘秦,同時便于控制讼渊、使用、測試尊剔。
redux不依賴于任意框架(庫)爪幻,只要subscribe相應(yīng)框架(庫)的內(nèi)部方法,就可以使用該應(yīng)用框架保證數(shù)據(jù)流動的一致性。
二挨稿、 Redux的設(shè)計思想
(1)Web 應(yīng)用是一個狀態(tài)機仇轻,視圖與狀態(tài)是一一對應(yīng)的。
(2)所有的狀態(tài)奶甘,保存在一個對象里面篷店。
三、 Redux的三原則
1. Single source of truth單一數(shù)據(jù)源臭家,數(shù)據(jù)流向也是單一方向疲陕。整個應(yīng)用的state,存儲在唯一一個javascript對象中钉赁,同時也只有一個store用于存儲這個對象.
2. State is read-only狀態(tài)是只讀的蹄殃。唯一能改變state的方法,就是觸發(fā)action操作你踩。action是用來描述正在發(fā)生的事件的一個對象诅岩。
3. Changes are made with pure functions在改變state tree時,用到action带膜,同時也需要編寫對應(yīng)的reducers才能完成state改變操作吩谦。
三、 Redux的基本概念
1. Redux使用了類似于Flux的單向數(shù)據(jù)流膝藕,但是它只有一個單一的store對象式廷,這個store對象通過克隆原始的store來改變,它調(diào)用reducer將action和之前的state作為參數(shù)束莫,reducer并不產(chǎn)生副作用懒棉。
2.action是一個簡單的對象,其中包含了需要執(zhí)行的操作的類型以及一些負(fù)載览绿。改變由reducers 來執(zhí)行,reducers 是沒有副作用的純函數(shù)穗慕,將先前的state和一個action作為參數(shù)饿敲。它們會返回由應(yīng)用action產(chǎn)生的
新的state。
3.Redux提供了一個方法逛绵,可以將reducers合并成一個怀各,當(dāng)store被創(chuàng)造出來的時候,它可以做一個簡單的調(diào)用术浪。
4.RN中state狀態(tài)的改變只存在當(dāng)前組件的生命周期中瓢对,Redux是為了將組件的生命周期擴大到APP被殺死,而不是單純在組件生命周期中
3.1 store
1. Store對象包含所有數(shù)據(jù)胰苏。如果想得到某個時點的數(shù)據(jù)硕蛹,就要對 Store 生成快照。這種時點的數(shù)據(jù)集合,就叫做 State法焰。
2. Store 就是把 Reducer 和 action 聯(lián)系到一起的橋梁秧荆。Store 接收 Action 的數(shù)據(jù)并將其連同當(dāng)前的 state樹 (包含所有 state 的一種特殊的數(shù)據(jù)結(jié)構(gòu),是一個單一的對象)發(fā)給 Reducer埃仪。
3. 當(dāng)前時刻的 State乙濒,可以通過store.getState()拿到。
4. Redux 提供createStore這個函數(shù)卵蛉,用來生成 Store颁股。
例子:
import {AppContainer} from 'react-hot-loader';
import createStore from 'redux/lib/createStore';
import combineReducers from 'redux/lib/combineReducers';
import {Provider} from 'react-redux';
import * as reducers from './reducers';
// combineReducer的簡單實現(xiàn): 把所有子 Reducer 放在一個文件里面,然后統(tǒng)一引入
const reducer = combineReducers({
...reducers
});
export const store = createStore(
reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() // eslint-disable-line
);
ReactDOM.render(
<AppContainer>
<Provider store={store}>
<App />
</Provider>
</AppContainer>,
document.getElementById('approot')
);
注意:
1. 參數(shù)1-reducer:store.dispatch方法會觸發(fā) Reducer 的自動執(zhí)行傻丝。為此甘有,Store 需要知道 Reducer 函數(shù),做法就是在生成 Store 的時候桑滩,將 Reducer 傳入createStore方法
2. 參數(shù)2:表示 State 的最初狀態(tài)梧疲。這通常是服務(wù)器給出的。window.__REDUX_DEVTOOLS_EXTENSION__就是整個應(yīng)用的狀態(tài)初始值运准。注意幌氮,如果提供了這個參數(shù),它會覆蓋 Reducer 函數(shù)的默認(rèn)
初始值胁澳。
3. combineReducers:用于 Reducer 的拆分该互。你只要定義各個子 Reducer 函數(shù),然后用這個方法韭畸,將它們合成一個大的 Reducer宇智。
4. React-Redux 提供Provider組件,Provider在根組件外面包了一層胰丁,這樣一來随橘,App的所有子組件就默認(rèn)都可以拿到store了
3.2 action
1. State 的變化,會導(dǎo)致 View 的變化锦庸。但是机蔗,用戶接觸不到 State,只能接觸到 View甘萧。所以萝嘁,State 的變化必須是 View 導(dǎo)致的。Action 就是 View 發(fā)出的通知扬卷,表示 State 應(yīng)該要發(fā)生變化了牙言。
2. Action 是一個對象。它包含一個類型以及相關(guān)數(shù)據(jù)怪得,其中的type屬性是必須的咱枉,表示 Action 的名稱卑硫。其他屬性可以自由設(shè)置
3. store.dispatch()是 View 發(fā)出 Action 的唯一方法,此方法會自動調(diào)用 Reducer庞钢,得到新的 State拔恰。
例子:
/**
* Created by work on 17/6/15.
*/
export const REFRESH_PATCH_ITEMDATA = 'REFRESH_PATCH_ITEMDATA';
export const refreshPatchItemData = (patchItemData) => ({
type: REFRESH_PATCH_ITEMDATA,
patchItemData
});
3.3 reducer - 更新state
1. reducer是一個純函數(shù),Action只是用來描述事情發(fā)生,具體的業(yè)務(wù)邏輯操作和state的更新是交給Reducer來處理基括,它接收一個之前的 state和一個 Action颜懊;Reducer 函數(shù)里面不能改變 State,必須返回一個全新的對象风皿。
2. Redux 提供了一個combineReducers方法河爹,用于 Reducer 的拆分。你只要定義各個子 Reducer 函數(shù)桐款,然后用這個方法咸这,將它們合成一個大的 Reducer。
例子:
/**
* Created by work on 17/6/15.
*/
import {REFRESH_PATCH_ITEMDATA} from '../actions/patchReport';
const initState = {
patchItemData: null
};
export default (state = initState, action) => {
switch (action.type) {
case REFRESH_PATCH_ITEMDATA: {
const {patchItemData} = action;
return Object.assign({}, state, {patchItemData});
}
default:
return state;
}
};
四魔眨、應(yīng)用
方法-:通過connect獲取存入到redux中的值
image.png
方法二:
更加簡潔的方法:
import {refreshPatchItemData} from '../../../../actions/patchReport';
存值:refreshPatchItemData是你在action中寫的方法
store.dispatch(refreshPatchItemData(json.data)); // action
取值:patchReport是在reducers中index.js中對應(yīng)的redurce文件的名字媳维,patchItemData是文件中設(shè)置的初始值
store.getState().patchReport.patchItemData // redurce
五、工作流程
image.png
1. 用戶發(fā)出action(可以參考Redux的基本概念中3.2action的第一條)
store.dispatch(action);
2. 然后遏暴,Store 自動調(diào)用 Reducer侄刽,并且傳入兩個參數(shù):當(dāng)前 State 和收到的 Action。 Reducer 會返回新的 State 朋凉。
3. State 一旦有變化州丹,Store 就會觸發(fā)重新渲染 View。
Action --> Store --> Reducers --> Store --> View --> Action
參考:阮一峰老師的入門教程