用JS打造一款記賬App——Redux架構設計

上一篇我們學習了構建一個react項目以及配置webpack并運行項目,這篇我們在引入redux之前學習它的運行機制及設計思路。

Redux的架構思想

1. state和store 的概念

state是React中定義的應用狀態(tài),本質是一個數(shù)據(jù)集的普通對象,例如

/** 應用初始state **/
{
    status: 0,
    todos: []
}

store是應用狀態(tài)state的管理者,包含四個函數(shù):

getState() #獲取整個state
dispatch(action) #觸發(fā)state改變的唯一途徑
subscribe(listener) #可以理解為DOM中的addEventListener
replayceReducer(nextReducer) #一般在Webpack按需加載的時候用

二者的關系 state = store.getState()

Redux規(guī)定:一個應用只應有一個單一的store,其管理著唯一的應用狀態(tài)state且不能直接被修改,若要改變state,必須執(zhí)行dispatch一個action,這是修改應用狀態(tài)的唯一方法。

現(xiàn)在您只需要記住action只是一個包含type屬性的普通對象即可
例如{type:'INCREMENT'}

我們知道了state是通過store.getState()獲取的,那么store是怎么來的呢?那就需要用到了Redux定義的createStore方法了。

import { createStore } from 'redux'
...
//store是將reducer傳入生成的
const store = createStore(reducer, initialState) 

現(xiàn)在您只需要記住reducer是一個函數(shù),負責更新并返回一個新的state,而initialState主要用于前后端同構的數(shù)據(jù)同步(詳情請關注React服務端渲染)

2. reducer

這里我們又要用到Redux中定義的另外一個方法combineReducers。

import { combineReducers } from 'redux'
...
const rootReducer = combineReducers({
  captchaData,
  loginState,
  status,
  userInfo
})

export default rootReducer

具體工作原理是dispatch執(zhí)行action之后,reducer負責根據(jù)action的type屬性重新將對應action的payload值賦給nextState

3.Action

上面我們提到了action實質的包含type屬性的普通對象,這個type是實現(xiàn)用戶行為的關鍵。例如我們增加一個支出分類

{
    type: 'ADD_CATEGORY',
    payload: {
        id:1,
        content:'交通'
    }
}

當然,action可以根據(jù)具體的業(yè)務來自由設定,唯一的必要屬性就是type,甚至我們可以寫一個只包含type屬性的action

下面的action都是合法的

{
    type: 'ADD_CATEGORY',
    id:1,
    content:'交通'
}

{
    tyep: 'ADD_CATEGORY',
    aabbcc: {
        id: 1,
        content: '交通'
    }
}
{
    type: 'ADD_CATEGORY'
}

雖然沒有約束,但最好還是遵循規(guī)范

這里有一個思考問題,action難道就只是包含type等一些屬性的對象嗎?這里留一個懸念,后面我在具體用Redux的過程中再講。

Redux優(yōu)缺點

Action Creator => action => store.dispatch(action) => reducer(state, action) => 原state state = nextState

優(yōu)點:清晰的數(shù)據(jù)流向,讓我們處理復雜的業(yè)務邏輯,可以更加方便的梳理業(yè)務線,action只負責執(zhí)行邏輯操作和數(shù)據(jù)獲取,reducer只負責返回數(shù)據(jù)集,然后connect給react中的組件使用,讓react只關心交互界面的邏輯,無需關心數(shù)據(jù)邏輯。
另外我們使用redux還有如下好處

  • 方便地能夠將應用狀態(tài)存儲到本地并且重啟動時能夠讀取恢復狀態(tài)
  • 方便地能夠在服務端完成初始狀態(tài)設置,并且完成狀態(tài)的服務端渲染
  • 能夠序列化記錄用戶操作,能夠設置狀態(tài)快照,從而方便進行Bug報告與開發(fā)者的錯誤重現(xiàn)
  • 能夠將用戶的操作或者事件傳遞給其他環(huán)境而不需要修改現(xiàn)有代碼
  • 能夠添加重放或者撤銷功能而不需要重構代碼
  • 能夠在開發(fā)過程中實現(xiàn)狀態(tài)歷史的回溯,或者根據(jù)Action的歷史重現(xiàn)狀態(tài)
  • 能夠為開發(fā)者提供全面透徹的審視和修改現(xiàn)有開發(fā)工具的接口,從而保證產品的開發(fā)者能夠根據(jù)他們自己的應用需求打造專門的工具
  • 能夠在復用現(xiàn)在大部分業(yè)務邏輯的基礎上構造不同的界面

使用Redux我們必須遵循Redux的守則

  • 必須使用基本對象與數(shù)組來描述應用狀態(tài)
  • 必須使用基本的對象來描述系統(tǒng)變化
  • 必須使用純函數(shù)來處理系統(tǒng)中的業(yè)務邏輯

缺點:由于必須遵守Redux的守則,即使很簡單的業(yè)務邏輯,我們也必須有store,reducer,action.type。這樣給人的感覺就是殺雞用牛刀,所以對于簡單的業(yè)務邏輯,我們無需引用Redux庫。

最后,Redux真正的靈魂在于其設計思想,很多時候并不一定需要引用Redux庫本身,但可以嘗試使用redux的思想。

import React, { Component } from 'react'

class Counter extends Component {
  state = { value: 0 }
  
  increment = () => {
    this.setState(prevState => ({
      value: prevState.value + 1
    }))
  }

  decrement = () => {
    this.setState(prevState => ({
      value: prevState.value - 1
    }))
  }
  
  render() {
    return (
      <div>
        {this.state.value}
        <button onClick={this.increment}>+</button>
        <button onClick={this.decrement}>-</button>
      </div>
    )
  }

使用redux,我們可能會有禁用Local State的習慣,其實Local State有時候恰恰是用最簡單的方法幫我們解決問題。我們對上面代碼用redux思想進行改造

import React, { Component } from 'react'

const counter = (state = { value:0 }, action) => {
    switch (action.type) {
        case 'INCREMENT':
            return { value: state.value + 1}
        case 'DECREMENT':
            return { value: state.value - 1}
        default:
            return state
    }
}

class Counter extends Component {
    state = counter(undefined, {})
    
    dispatch(action) {
        this.setState(prevState => counter(prevState, action))
    }
    
    increment = () => {
        this.dispatch({type: 'INCREMENT'})
    }
    
    decrement = () => {
        this.dispatch({type: 'DECREMENT'})
    }
    
    render() {
      return (
         <div>
         {this.state.value}
            <button onClick={this.increment}>+</button>
            <button onClick={this.decrement}>-</button>
         </div>
    )
  }
}

總結

  • store由Redux的 createStore(reducer) 生成
  • state通過store.getState()獲取,本質是一個存儲整個應用狀態(tài)數(shù)據(jù)集的對象
  • reducer用于更新state并返回nextState的函數(shù),且reducer必須有返回值,否則nextState將為undefined
  • action是一個包含type屬性的普通對象,用于dipatch來改變state

這一篇我們理解了Redux的幾個概念以及設計思想,下一篇我們要在項目中引用Redux庫并學習怎么使用它。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容