淺淺談Redux

if 讀完了 then 你能瞭解到:vue

  • 好鋼用在刀刃 - redux的應用場景
  • 萬變不離其宗 - redux的基本思路

一些嘮叨

最近有個任務,就是須要在一個開源項目上進行擴展開發,而這個開源項目用到的是很是主流的 react 和 react-redux,近些年一直在跟 vue 打交道(廣告植入:好比開源了一個 vue 版本的 ncform 項目),冷落了 react 有一段時間了,恰好趁機重溫下 react 及其周邊相關的技術生態java

react-redux,其實就是 redux 的 react 版本,方便 redux 在 react 中使用。react

而 redux,是 javaScript 應用狀態管理容器,是參考 flux 設計模式的一種實現(vue 的 vuex 也是相似的實現),它獨立於各類 web 框架但又可融入於各類 web 框架。git


哪裏纔是 redux 用武之地

不少人會認爲,引入 redux 會增長應用的複雜性。確實不簡單,但存在即合理,因此什麼場景下適合使用 redux 就很關鍵了。github

我就開發一個活動頁。奉勸你不要用 redux 啦,一點好處都沒有,只會增長複雜性。web

切記:不要爲了用而用 - 然而現實中這種現象是大量存在的vuex

當一個應用的功能愈來愈多時,開始進行功能模塊拆分,這個時候,就會遇到一個問題,功能模塊之間共享的數據如何處理,好比登陸用戶的信息。redux

例子能再具體點嗎?好吧,但仍是登陸用戶信息,哈哈。設計模式

好比你在用戶模塊修改了頭像,而後頂欄上的登陸頭像要實時跟着更新,這個時候,實際上是用戶模塊和頂欄共享了你的用戶頭像信息api

解決這種可能有N種方法,今天既然聊 redux,那就專心講它吧

當你把數據梳理一下,你會發現有些數據是在模塊內共享的,有些數據是在模塊間共享的,咱們將在模塊間共享的稱之爲應用級別的數據,即 Application 級別,redux 就是專門處理這種級別數據的解決方案


redux 的基本思路

咱們用 redux 官方的 todo app 例子來說解( Warning: 僅爲了說得簡單,講得明白,這種小應用是不適合引入 redux 的 )

你的應用有着一份描述着狀態(state)的數據,可能以下:

🔸 術語
State: 應用級別的狀態數據

{
  todos: [{
    text: 'Eat food',
    completed: true
  }, {
    text: 'Exercise',
    completed: false
  }],
  visibilityFilter: 'SHOW_COMPLETED'
}
複製代碼

這份 state 是靜態的,你能夠理解爲就是應用最初的狀態。

當我完成了 Exercise 項,我就打個勾,表示我完成了。此時就須要更改下應用的狀態,須要把 Exercise 那一項 的completed 由 false 改爲 true。

怎麼更改呢?直接把值改了不就完事了?

若是直接改變 state 對象的屬性值,就斷了 state 更改的軌跡,簡單講就是你修改了一個對象的屬性值,你就很難追蹤屬性值更改前是什麼樣子了。這在調試排查問題的時候很是有用。

必定有更好的方法,可參考下事件的機制。因此當想更改狀態時,咱們派發(dispath)一個操做(action),描述清楚咱們想幹什麼,而不是直接就幹了。一個操做的描述可能以下:

{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }
複製代碼

🔸 術語
dispatch: 經過該方法主動派發操做
action: 描述操做的內容,type 值必須提供,指定行爲的類型,至關於事件的名稱

用派發操做的好處:
將每一個更改描述爲一個操做,讓咱們清楚地瞭解應用程序中發生的狀況。 若是發生了變化,咱們就知道它爲何會改變,操做就像麪包屑,使得應用狀態的變化有跡可循

OK,至此啥事還沒作,只是嘴上嚷嚷我要作什麼,那總得有實際處理的方法吧。

沒錯,這些實際修改狀態的方法稱爲 reducer。實現可能以下:

function visibilityFilter(state = 'SHOW_ALL', action) {
  if (action.type === 'SET_VISIBILITY_FILTER') {
    return action.filter
  } else {
    return state
  }
}
function todos(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return state.concat([{ text: action.text, completed: false }])
    default:
      return state
  }
}
複製代碼

🔸 術語
reducer:它負責接收當前 state 和 action,而後按照 action 的 type,根據當前 state 進行操做,最終返回一個全新的 state(返回全新的 state 保證了 數據修改的可追溯性)。

你會發現 visibilityFilter 返回的是查詢條件字符串,而 todos 返回的是列表項數組列表。把它們返回的數據合併起來,就是一個完整的應用狀態,以下:

function todoApp(state = {}, action) {
  return {
    todos: todos(state.todos, action),
    visibilityFilter: visibilityFilter(state.visibilityFilter, action)
  }
}
複製代碼

OK,到此爲此,想幹什麼也說了,實際作事的也講了,但好像仍是雲裏霧裏,腦殼裏依然沒有很清晰的全局的畫面,好像還少了什麼東西。

告訴你,少了一個管家,它管着應用的狀態,它就是 store。

🔸 術語
Store: 管理應用狀態數據,負責把 action, reducer 等串起來

咱們借用 redux 的一些 api 來完整描述一個數據修改的全過程

  1. 建立 store。經過 reducer 做爲參數,store 就能夠經過 reducer 獲取到應用狀態的數據結構
let store = createStore(todoApp)
複製代碼
  1. 監聽變化。你能夠在應用狀態發生變化時作一些事,好比更新DOM
function listener() { console.log(store.getState()) }
store.subscribe(listener)
複製代碼
  1. 派發操做。由於 store 擁有 reducer,因此只要把 action 交給 reducer 處理便可。處理後能夠通知執行第2步中訂閱的一些操做
let action = { type: 'ADD_TODO', text: 'Go to swimming pool' }
store.dispatch(action)
複製代碼

😫修改了好屢次,終於寫完了。。。


寫在最後

接下來的內容跟本文一毛錢關係都沒,只是一如既往地打一波廣告:

ncform,一種使人愉悅的表單開發方式,僅需配置便可生成表單UI及其交互行爲。
自帶豐富的 標準組件 和 校驗規則,開箱即用。
具有強大的 控件交互 和 擴展能力,作你所想。
github: github.com/ncform/ncfo…

注:目前只有 vue 版本,但願在不久的未來,有時間發佈 react 版本

tags: react, flux, react-redux, redux

相關文章
相關標籤/搜索