十分鐘理解Redux核心思想,過目不忘。

龍捲風發表於2019-02-16

白話Redux工作原理。淺顯易懂。
如有紕漏或疑問,歡迎交流。

Redux 約法三章

唯一資料來源(state)

雖然redux中的statereact沒有聯絡,但可以簡單理解為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(資料流):

  1. UI發出動作,如click, submit;
  2. action, 描述發生了什麼;
  3. reducer處理髮生的事情,生成新state;
  4. store被更新;
  5. 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提供了一下方法:

  1. store.getState() 獲取當前state
  2. store.dispatch(action) 更新state
  3. store.subscribe(listener) store更新後回撥listener,回撥函式裡面可以呼叫store.getStore()來獲取更新後得state喲~
  4. 取消listener的方式比較特別:呼叫一次store.subscribe(sameListner)

ps: 如有紕漏或疑問,歡迎交流。
先寫這麼多,有時間繼續更新。

相關文章