Redux

介紹 Redux

Redux是一個(gè)數(shù)據(jù)狀態(tài)管理插件如输,搭配 React 特別合適利耍,詳細(xì)的用法可見(jiàn)Redux官網(wǎng)

使用場(chǎng)景

無(wú)論是移動(dòng)端還是 pc 端量没,當(dāng)你使用 React 或者 vue 開(kāi)發(fā)組件化的 SPA 程序時(shí)扯再,組件之間共享信息是一個(gè)非常大的問(wèn)題荚板。例如,用戶(hù)登錄之后客戶(hù)端會(huì)存儲(chǔ)用戶(hù)信息(如userid队寇、頭像等)膘掰,而系統(tǒng)的很多個(gè)組件都會(huì)用到這些信息,例如收藏佳遣、點(diǎn)贊识埋、評(píng)論等。這些組件在用到用戶(hù)信息時(shí)零渐,難道每次使用都重新獲取一遍窒舟?———— 自然不是這樣。因此每個(gè)系統(tǒng)都需要一個(gè)管理多組件使用的公共信息的功能诵盼,這就是 Redux 的作用惠豺。同理,vue 也有相應(yīng)的工具拦耐,即 vuex 耕腾,可以自己去 github 上搜索相關(guān)資料。

初學(xué)者可能通過(guò)這幾句話無(wú)法真實(shí)理解它的用意杀糯,此時(shí)你只需要記咨ò场:只要使用 React 開(kāi)發(fā)系統(tǒng),你絕大部分都需要結(jié)合 Redux 來(lái)使用固翰,后面的課程我們?cè)敿?xì)講解 Redux 在實(shí)際項(xiàng)目中的使用狼纬,課程結(jié)束后,你就會(huì)明白其中的道理骂际。

安裝

如果單純使用 Redux 僅僅安裝 Redux 即可疗琉,執(zhí)行npm install redux --save,不過(guò)在 React 中使用 Redux 肯定會(huì)用到 react-redux 這一工具歉铝,因此這里一起安裝完盈简,執(zhí)行npm install react-redux --save

基本使用

可以參見(jiàn)./app/redux-demo.js中的例子,如下代碼

    // 定義計(jì)算規(guī)則柠贤,即 reducer
    function counter(state = 0, action) {
        switch (action.type) {
            case 'INCREMENT':
                return state + 1
            case 'DECREMENT':
                return state - 1
            default:
                return state
        }
    }

    // 根據(jù)計(jì)算規(guī)則生成 store
    let store = createStore(counter)

    // 定義數(shù)據(jù)(即 state)變化之后的派發(fā)規(guī)則
    store.subscribe(() => {
        console.log('current state', store.getState())
    })

    // 觸發(fā)數(shù)據(jù)變化
    store.dispatch({type: 'INCREMENT'})
    store.dispatch({type: 'INCREMENT'})
    store.dispatch({type: 'DECREMENT'})

簡(jiǎn)單幾十行代碼香浩,就詮釋了 Redux 的設(shè)計(jì)理念,這里簡(jiǎn)單分析一下:

  • Redux 是一個(gè)管理數(shù)據(jù)的工具臼勉,我們創(chuàng)建一個(gè)store變量用來(lái)管理數(shù)據(jù)邻吭。而這個(gè)store不是憑空創(chuàng)建的,創(chuàng)建它的前提是宴霸,得設(shè)定一個(gè)管理規(guī)則囱晴。以上代碼中,我們的管理規(guī)則是:數(shù)據(jù)(即state)默認(rèn)是 0瓢谢,傳入INCREMENT就加一畸写,傳入DECREMENT就減一
  • 創(chuàng)建store用來(lái)管理數(shù)據(jù),具體的管理形式是什么呢恩闻?第一艺糜,要通過(guò)一個(gè)函數(shù)來(lái)觸發(fā)數(shù)據(jù)的變化,即dispatch幢尚,觸發(fā)的時(shí)候一定要符合之前定制的規(guī)則,否則無(wú)效翅楼。第二尉剩,數(shù)據(jù)一旦發(fā)生變化時(shí),會(huì)導(dǎo)致怎樣后果毅臊,即subscribe中定義的函數(shù)會(huì)執(zhí)行理茎。第三,如何取得當(dāng)前的數(shù)據(jù)管嬉,即store.getState()皂林。這一塊,熟悉設(shè)計(jì)模式的同學(xué)不難理解蚯撩,這就是普通的發(fā)布和訂閱的設(shè)計(jì)模式础倍,也是js種慣用的設(shè)計(jì)模式。
  • 還有一點(diǎn)特別要注意胎挎,即在規(guī)則函數(shù)中沟启,數(shù)據(jù)變化時(shí)要return一個(gè)新的值,而不是直接修改原來(lái)的值犹菇。這一點(diǎn)和之前提到的Immutable.js一樣德迹,都是使用了不可變數(shù)據(jù)這一概念。這種設(shè)計(jì)方式明確了數(shù)據(jù)的變化時(shí)段揭芍,使得數(shù)據(jù)管理更清晰胳搞,復(fù)雜度更低。

------------------ 分割線 ------------------

Redux 和 React 集成

這塊一開(kāi)始介紹可能會(huì)感覺(jué)有點(diǎn)混亂,要做好心理準(zhǔn)備肌毅。

創(chuàng)建 store

跟上次講過(guò)得簡(jiǎn)單 demo 一樣币厕,首先也需要?jiǎng)?chuàng)建一個(gè)store,參見(jiàn)./app/store/configureStore.js的代碼芽腾。之前的 demo 提到旦装,創(chuàng)建store之前要有規(guī)則,這里的第一個(gè)參數(shù)就是這個(gè)規(guī)則摊滔,后面會(huì)詳細(xì)講到阴绢。

    const store = createStore(rootReducer, initialState,
        // 觸發(fā) redux-devtools
        window.devToolsExtension ? window.devToolsExtension() : undefined
    )

第二個(gè)參數(shù)即初始化的數(shù)據(jù),第三個(gè)參數(shù)可調(diào)起 chrome 擴(kuò)展程序艰躺,具體可參見(jiàn) redux-devtools

創(chuàng)建規(guī)則(Reducer)

使用 Redux 時(shí)呻袭,剛才提到的“規(guī)則”被稱(chēng)作reducer(就是一個(gè)統(tǒng)一的稱(chēng)呼,不比去糾結(jié))腺兴,因此這里的數(shù)據(jù)規(guī)則代碼都在./app/reducers目錄下左电。

先看userinfo.js的代碼,跟上次 demo 中的幾乎一樣页响,唯一的區(qū)別就是將 const 都寫(xiě)到了./app/constants/userinfo.js中篓足。之所以這樣做,是因?yàn)檫@些 const 會(huì)在多個(gè)文件中使用闰蚕,因此要抽象出來(lái)栈拖。

再看index.js的代碼,它用combineReducers這個(gè)函數(shù)對(duì)userinfo.js的數(shù)據(jù)進(jìn)行了封裝没陡,這樣做是為了更好的擴(kuò)展性涩哟。試想,一個(gè)系統(tǒng)中存儲(chǔ)在 Redux 中的數(shù)據(jù)可能會(huì)有很多盼玄,我們這里已經(jīng)有一個(gè)userinfo.js處理用戶(hù)數(shù)據(jù)贴彼,和可能哪天就再加nav.js處理導(dǎo)航數(shù)據(jù)、加ad.js處理廣告數(shù)據(jù)……

上次的demo中埃儿,state就是一個(gè)數(shù)據(jù)器仗,可以進(jìn)行state + 1state - 1,數(shù)據(jù)結(jié)構(gòu)非常簡(jiǎn)單蝌箍。而現(xiàn)在青灼,數(shù)據(jù)結(jié)構(gòu)復(fù)雜太多,必須分組管理妓盲。因此我們需要用state.userinfo來(lái)表示用戶(hù)數(shù)據(jù)杂拨,state.nav表示導(dǎo)航數(shù)據(jù),state.ad表示廣告數(shù)據(jù)…… ———— 這就是用combineReducers分裝各個(gè) reducer 的作用悯衬。

創(chuàng)建 action

上次的 demo 中弹沽,最后執(zhí)行數(shù)據(jù)變化時(shí)store.dispatch({type: 'INCREMENT'})檀夹,這里的{type: 'INCREMENT'}是我們手動(dòng)寫(xiě)上的,而在實(shí)際的應(yīng)用中策橘,我們需要用一些函數(shù)將它分裝起來(lái)炸渡,即./app/actions中的文件,雖然此處只有userinfo.js這一個(gè)文件丽已。

userinfo.js中蚌堵,我們把每個(gè)業(yè)務(wù)操作都分裝為一個(gè)函數(shù),該函數(shù)接收data沛婴,然后再根據(jù) reducer 的規(guī)則對(duì) data 進(jìn)行分裝吼畏,最后返回。當(dāng)然嘁灯,最后返回的結(jié)果肯定還是會(huì)交給dispatch來(lái)處理泻蚊,這是后面要說(shuō)的。

結(jié)合到 React

先看./app/index.js丑婿,重點(diǎn)注意下面這些代碼性雄。這里,創(chuàng)建了store并傳遞給<Provider>組件羹奉,然后讓<Provider>組件作為所有組件的根節(jié)點(diǎn)秒旋。

import { Provider } from 'react-redux'
import configureStore from './store/configureStore'

const store = configureStore()

render(
    <Provider store={store}>
        <Hello/>
    </Provider>,
    document.getElementById('root')
)

然后看./containers/Hello.jsx,注意下面這些代碼尘奏。通過(guò)下面的封裝滩褥,就把userinfouserinfoActions當(dāng)做props傳入到Hello中了,即在Hello組件中通過(guò)this.props.userinfothis.props.userinfoActions即可獲取數(shù)據(jù)和 actions

function mapStateToProps(state) {
    return {
        userinfo: state.userinfo
    }
}

function mapDispatchToProps(dispatch) {
    return {
        userinfoActions: bindActionCreators(userinfoActions, dispatch)
    }
}

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(Hello)

獲取了數(shù)據(jù)和 actions 該怎么用呢炫加?我們將它們傳遞給子組件,AB組件負(fù)責(zé)展示數(shù)據(jù)铺然,C組件負(fù)責(zé)觸發(fā)actions俗孝。具體可參見(jiàn)各個(gè)組件的源代碼。

    render() {
        return (
            <div>
                <p>hello world</p>
                <hr/>
                <A userinfo={this.props.userinfo}/>
                <hr/>
                <B userinfo={this.props.userinfo}/>
                <hr/>
                <C actions={this.props.userinfoActions}/>
            </div>
        )
    }

運(yùn)行代碼之后魄健,就會(huì)看到數(shù)據(jù)變化的效果了赋铝。


總結(jié):接下來(lái)的實(shí)際項(xiàng)目中,也會(huì)像上面這樣使用 Redux沽瘦,如果這里還有點(diǎn)不明革骨,接下來(lái)的課程也會(huì)再詳細(xì)講解————當(dāng)然,還是要盡早搞明白好

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末析恋,一起剝皮案震驚了整個(gè)濱河市良哲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌助隧,老刑警劉巖筑凫,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡巍实,警方通過(guò)查閱死者的電腦和手機(jī)滓技,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)棚潦,“玉大人令漂,你說(shuō)我怎么就攤上這事⊥璞撸” “怎么了叠必?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)原环。 經(jīng)常有香客問(wèn)我挠唆,道長(zhǎng),這世上最難降的妖魔是什么嘱吗? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任玄组,我火速辦了婚禮,結(jié)果婚禮上谒麦,老公的妹妹穿的比我還像新娘俄讹。我一直安慰自己,他們只是感情好绕德,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布患膛。 她就那樣靜靜地躺著,像睡著了一般耻蛇。 火紅的嫁衣襯著肌膚如雪踪蹬。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,842評(píng)論 1 290
  • 那天臣咖,我揣著相機(jī)與錄音跃捣,去河邊找鬼。 笑死夺蛇,一個(gè)胖子當(dāng)著我的面吹牛疚漆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播刁赦,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼娶聘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了甚脉?” 一聲冷哼從身側(cè)響起丸升,我...
    開(kāi)封第一講書(shū)人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎宦焦,沒(méi)想到半個(gè)月后发钝,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體顿涣,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年酝豪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涛碑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡孵淘,死狀恐怖蒲障,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瘫证,我是刑警寧澤揉阎,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站背捌,受9級(jí)特大地震影響毙籽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜毡庆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一坑赡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧么抗,春花似錦毅否、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至吞琐,卻和暖如春捆探,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背站粟。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工徐许, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卒蘸。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像翻默,于是被迫代替她去往敵國(guó)和親缸沃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容