Redux工作流解析
Redux是什麼
假設我們的業務有三個巢狀的元件ABC 元件A想要傳值給元件C 要先傳遞給元件B 交由B傳遞給C 在沒有引入Redux
的時候 我們只能通過這種原始的方法來傳遞 這時候 我們再假設 如果有一個 公共管理資料狀態的地方 我們每次傳遞值或者修改值 都從這個地方獲取 那不論業務多複雜 元件巢狀多深 我們都可以很方便的直接從這個管理倉庫裡 獲取到我們需要的資料 這就是Redux
一個 資料層
的框架 或者說是一個 狀態容器
瞭解Redux工作流
這張圖非常清晰的描述了 Redux
的工作流程 光看這一張圖可能會有一點晦澀難懂 但是我們可以換個說法 把整個工作流程想像成一個借書的過程
一個人來圖書館借書 他需要說一句話告訴管理員 要借什麼書 管理員要根據他提供的資訊 找到對應的書籍 然後拿給他 想象過這個過程以後 再來看這個過程
首先 React Component
這個元件就是需要借書的人 同時Store
就是這個圖書館的管理員 他需要告訴管理員 他要借什麼書 那麼這個Action Creators
就是記錄這個資訊 並且告知管理員 同時管理員接收到這個資訊以後 他需要查詢管理手冊 找到對應書籍 這個手冊就對應Reducers
對應到實際開發到業務邏輯裡 其實就是 View
建立了一個action
通過dispatch
派發到Store
然後Store
會自動轉發到Reducers
那麼Reduces就可以接收到這個action 同時根據action來處理業務邏輯 並返回給Store
那麼接下來一起來看程式碼是如何實現的吧
使用Redux完成TodoList
ps:由於講述的是Redux 所以掠過了基礎的React元件部分
-
安裝Redux
npm install redux --save
-
再一次回想流程 我們需要一個Store(圖書館管理員) 在src目錄下新建一個Store資料夾 並建立
index.js
生成Store
接收一個reducer
引數(對應圖書館管理員的管理手冊) 有了手冊才可以找到對應書籍對吧~// store.js import { createStore } from 'redux' import reducer from './reducer.js' const Store = creaeStore(reducer) 複製程式碼
-
上面已經提到了我們需要一個
reducer
所以 我們新建一個reducer.js
同時需要注意的是reducer.js
是一個純函式 上文已經提到過 這個檔案是一個管理手冊 也就說 存放了書籍的具體資訊(需要被管理的資料)
以及如何處理書籍(業務邏輯)
-
reducer可以接收兩個引數 一個是
action
一個是state
預設情況下 同時可以定義一組需要被統一管理的資料 把這個需要被管理的資料賦值給state 至於action
我們一會兒再聊
// reducer.js
const originData = {
inputValue: '',
list: []
}
export default const reducer = (state = originData, action) => {
return state
}
複製程式碼
- 在元件內部引入
Store
同時store提供了getState()
這個API 可以讓我們獲取定義好的state 既然獲取了資料 那麼如果修改了資料 我們也是需要讓元件知道的 所以需要使用store提供給我們的另一個APIsubscribe
這裡定義的handleStoreChange
其實只做一件事 也就是再次重新獲取state
// 獲取store裡的資料
import store from './Store/'
constructor() {
// 獲取資料
this.state = store.getState()
// 元件訂閱store
store.subscribe(this.handleStoreChange)
}
handleStoreChange() {
this.setState(store.getState())
}
複製程式碼
- 執行到上面那一步我們就可以在我們的業務元件中使用
redux
了 在對應業務元件中引入這個Store
同時我們再次回顧上問中的Redux工作流的那張圖 當有了管理員(store)
並且有了管理手冊以後(reducer)
以後 我們現在只差一步了 也就是告訴管理員 我們需要借什麼書(操作什麼資料)
也就是元件向Store
派發一個action
的過程
// 元件派發action
// 元件對應的繫結事件
handleValueChange(e) {
// 建立一個action type表示要做啥 value 表示需要傳遞的值
const action = {
type: 'change_input_value',
value: e.target.value
}
store.dispatch(action) //store接收到事件以後 需要轉發給reducers 交由reducers處理
}
複製程式碼
-
當程式碼寫到這裡 回頭再去看一次上文提到的比喻 看看發生了什麼 首先 借書人
view/React Component
通過一句話action
告訴了管理員Store
要借什麼書 這個時候 管理員需要查閱手冊 來返回對應的書newState
所以我們回到reducer裡看看 該怎麼實現需求-
還記得之前定義
reducer.js
的時候 reducer函式接收的引數裡有action
麼 這個action
其實就是store
自動轉發給reducer
的 所以我們可以在reducer
裡拿到對應的action
並且根據action定義的type不同 處理不同的業務邏輯 -
同時我們還需要注意一點 在Redux之中 真正可以修改的資料的 其實只有Store 並不是修改的方法寫在reducer裡 reducer就可以修改資料 所以我們需要一個返回一個新值給到Store
-
const originData = {
inputValue: '',
list: []
}
//reducer.js
export default (state = originData, action) => {
if (action.type === 'change_input_value') {
// 返回一個新的state
const newState = JSON.parse(JSON.stringify(state))
newState.inputValue = action.value
return newState // store會接收到這個newState 並且會把原有資料替換成該資料 真正有權修改資料的還是Store本身
}
return state
複製程式碼
-
寫到這裡 其實我們就完成了redux的初步使用 以及完整的講解了redux的工作流程 完成了TodoList的第一個功能 順利輸入內容
-
TodoList裡剩下的兩個功能就是 點選新增的時候 展示區域顯示輸入的值 以及在展示區域點選對應項 則可以刪除對應項 其實也就是繼續在元件內的對應函式裡建立不同的action 並且在reducer裡對對應的action進行處理即可
-
待優化的點 可以建立
action creators
統一管理action的建立 以及actionTypes
的定義 減少因為定義type時發生的拼寫錯誤