白話Redux工作原理。淺顯易懂。
如有紕漏或疑問,歡迎交流。
Redux 約法三章
唯一資料來源(state)
雖然redux
中的state
與react
沒有聯絡,但可以簡單理解為react元件中的this.state
。html
文件只是state
的一種表現形式。所有html
的資料應該都是直接或間接來自於state
,否則UI檢視是無法因state
改變而更新的。
資料來源(state)只讀
不應該直接修改state
資料。
對於陣列使用:
Array.prototype.slice()//對陣列進行拷貝
//使用ES6:
[...state, ...newState]
對於物件使用:
Object.assign({}, state, change1, change2...)//對物件進行拷貝
//使用ES6:
{...state, ...newState}
通過純函式(pure function)改變資料來源(state)
pure function
: 無其他API(包括Math, Date等)呼叫,無非同步操作,preState => newState。
Redux資料流
簡單介紹store
/reducer
/action
, 比較簡潔,請牢記於心。
store
UI唯一資料來源,可以理解為react中的state,store資訊的變化會觸發檢視更新.
action
物件。必須擁有type屬性,用來描述發生什麼。可選擇攜帶發生時的資料,如使用者輸入的input value。切記:僅僅用來表述發生了什麼。
reducer
pure function(上面有解釋)。根據action.type來做出反應,(preState, action) => newState,生成的state是用來改變store的。
所以,data flow(資料流):
- UI發出動作,如click, submit;
- action, 描述發生了什麼;
- reducer處理髮生的事情,生成新state;
- store被更新;
- UI響應store更新
- …
Redux action
舉幾個例子,可能會比較直觀:
{
type: “TOGGLE_TODO”, //這個type屬性必須要,必須是字串
index: 5 //附加資訊,自己根據需要選擇是否加入
};
{
type: “ADD_TODO”,
text:“學習Redux” //附加資訊,這裡是input value
}
沒別的,就是這麼簡單。
有時候可以使用action生成器(action creators)來批量生產相似action物件,如:
//我需要根據不同的input value來生成高度相似的action:
function (text) {
return {
type: "ADD_TODO",
text: text //附加的資訊
}
}
說明
雖然上面資料流提到,action通過reducer處理生成newState後才能夠更改store資訊。但是為了更好的語義程式設計,Redux通過語句store.dispatch(action)
來更新store,reducer對action的處理在內部處理。
Redux reducer
很簡單
(theState, action) => (newState);
//僅僅只是根據action.type處理一下需要更新的state
來看一個相對完整的reducer:
function todoApp(state = initialState, action) { //注意需要處理undefined情況下的state預設值
switch (action.type) { //根據action.type來判斷
case "SET_VISIBILITY_FILTER":
return Object.assign({}, state, {
visibilityFilter: action.filter
})
case “ADD_TODO”: //處理“ADD_TODO”的action type
//返回新state(newState),注意不要直接改變state,物件使用了
//Object.assign()。也可以使用ES的...操作符
return Object.assign({}, state, {
todos: [
...state.todos,
{
text: action.text,
completed: false
}
]
})
case “TOGGLE_TODO”: //處理“TOGGLE_TODO”的action type
return Object.assign({}, state, {
todos: state.todos.map((todo, index) => {
if (index === action.index) {
return Object.assign({}, todo, {
completed: !todo.completed
})
}
return todo
})
})
default:
return state
}
}
Redux store
store
UI檢視唯一資料來源(直接或間接),可以獲取state,更新state,監聽state變化,取消監聽。所以store提供了一下方法:
-
store.getState()
獲取當前state -
store.dispatch(action)
更新state -
store.subscribe(listener)
store更新後回撥listener,回撥函式裡面可以呼叫store.getStore()來獲取更新後得state喲~ - 取消listener的方式比較特別:再呼叫一次
store.subscribe(sameListner)
ps: 如有紕漏或疑問,歡迎交流。
先寫這麼多,有時間繼續更新。