關(guān)于redux的發(fā)展惩琉,其實(shí)我也不太清除,似乎使用React的都會(huì)過(guò)度到Redux诵次,大概算是React的全家桶之一吧秒裕,這里在了解Redux之前袱蚓,不妨先了解下React設(shè)計(jì)應(yīng)用的一些特性:
React 算是V層框架,它的組件化開(kāi)發(fā)和單向數(shù)據(jù)流構(gòu)特性構(gòu)成了它設(shè)計(jì)的核心思想几蜻,組件化開(kāi)發(fā)喇潘,將一個(gè)頁(yè)面劃分成多個(gè)組件,獨(dú)立開(kāi)發(fā)每塊功能獨(dú)立的組件 梭稚,使得頁(yè)面靈活可插拔可復(fù)用颖低,然而組件的獨(dú)立劃分也必然會(huì)帶來(lái)組件間的數(shù)據(jù)交互問(wèn)題,因此對(duì)應(yīng)提出了單向數(shù)據(jù)流的特性哨毁,要求設(shè)計(jì)好state數(shù)據(jù)結(jié)構(gòu)枫甲,并放置在合理的位置,使得數(shù)據(jù)最大化的單向流動(dòng)扼褪,然而盡管如此想幻,在實(shí)際開(kāi)發(fā)中,我們?nèi)员苊獠涣耸褂梅聪驍?shù)據(jù)流话浇,詳見(jiàn)thinking React
一般來(lái)說(shuō)脏毯,React的這兩個(gè)特性,基本能合理設(shè)計(jì)并開(kāi)發(fā)出許多結(jié)構(gòu)不錯(cuò)的應(yīng)用幔崖,但隨著應(yīng)用的規(guī)模龐大食店,把state作為數(shù)據(jù)層,就需要多個(gè)數(shù)據(jù)層(state)對(duì)應(yīng)多個(gè)組件(view) 赏寇,那么假設(shè)state和view交互構(gòu)成了如下數(shù)據(jù)流:
隨著應(yīng)用的龐大吉嫩,一些反向數(shù)據(jù)流的存在就會(huì)造成錯(cuò)綜復(fù)雜,不可預(yù)測(cè)的問(wèn)題嗅定。
然而在Redux認(rèn)為自娩,用戶(hù)在view層對(duì)數(shù)據(jù)的操作只能發(fā)起action,也就是將上面的數(shù)據(jù)流結(jié)構(gòu)轉(zhuǎn)換為如下結(jié)構(gòu):
從上圖可以看出渠退,引入了actions忙迁,從而將錯(cuò)綜復(fù)雜的數(shù)據(jù)流變成了單向數(shù)據(jù)流(這里暫時(shí)不管圓圈里面是什么),進(jìn)而強(qiáng)化了React的單向數(shù)據(jù)流的核心思想碎乃。
因此姊扔,引入了redux使得數(shù)據(jù)的變動(dòng)變得可追溯,結(jié)構(gòu)更清晰梅誓。
有了上面的過(guò)度后恰梢,接下來(lái)就該討論,redux是如何做到這種數(shù)據(jù)流動(dòng)的梗掰,關(guān)于redux的設(shè)計(jì)核心删豺,這里先設(shè)計(jì)這幅循環(huán)圖來(lái)直接解釋?zhuān)?/p>
上圖是一個(gè)比較好解釋redux數(shù)據(jù)流的循環(huán)圖,這幅圖里有五個(gè)部分五個(gè)箭頭愧怜,這里就先簡(jiǎn)單介紹這五大塊呀页,再對(duì)每塊具體操作詳細(xì)分析。
1. 有defines箭頭可以看出拥坛,只有State的變化才會(huì)引起UI的變化蓬蝶。
2. 由triggers箭頭可以看出,UI 只能統(tǒng)一觸發(fā) Actions操作猜惋。
3. 由sent to可以看出丸氛,Actions需要分發(fā)(dispatch)到Reducers上去決定如何執(zhí)行。
4. 由Updates可以看出著摔,Reducers可以更新Store中的狀態(tài)缓窜,然而Store中的狀態(tài)是什么呢?
5. 由contains可以看出Store可以認(rèn)為是State的集合,也就是說(shuō)禾锤,Reducers決定著State如何改變私股,Store用于統(tǒng)一化管理State。
那么Redux這種循環(huán)流向的特性恩掷,也就決定著在設(shè)計(jì)應(yīng)用流程上應(yīng)該遵照的統(tǒng)一化步驟:
1. 首先是actions倡鲸,actions簡(jiǎn)單來(lái)說(shuō)就是用戶(hù)操作UI界面能發(fā)起的動(dòng)作,它其就是用json對(duì)象定義的黄娘,其中必須要有一個(gè)type字段峭状,指明是哪種類(lèi)型的操作,type字段的值一般是字符串逼争,使用字符串常量會(huì)更好一些优床,同時(shí)可以傳遞該操作需要傳遞的參數(shù)。
2. 其次需要設(shè)計(jì)的是Reducers誓焦, Reducers其實(shí)是用來(lái)決定不同類(lèi)型(type)的actions需要怎么修改state胆敞,(這也就意味著在此之前最好先考慮一下state結(jié)構(gòu)的設(shè)計(jì)),Reducers必須是一個(gè)純函數(shù)罩阵,它接受舊的state和actions竿秆,返回的是新的state,在redux-react中稿壁,可以根據(jù)類(lèi)型不同設(shè)計(jì)不同的reducers幽钢,這也就對(duì)應(yīng)著state結(jié)構(gòu)中不同的字段了,最后將他們combine傅是。
3. 對(duì)于combine的reducers匪燕,需要將其注冊(cè)到統(tǒng)一且唯一的store中去才能達(dá)到統(tǒng)一化管理的效果,然而要想在react中引入store并在整個(gè)組件中使用喧笔,就需要react-redux提供的Providers組件了帽驯,用它來(lái)讓React組件中共享store。
4. 關(guān)于UI組件书闸,這里放在最后尼变,其實(shí)也可以不這樣,先設(shè)計(jì)UI組件也是可以的浆劲,只是這里要討論state將要如何決定UI組件的改變嫌术,而且UI組件又如何發(fā)起action,這兩步是打通整個(gè)循環(huán)的最基礎(chǔ)也是最重要的一步牌借,為了區(qū)分UI組件和交互相關(guān)度气,在Redux中提出了兩種不同類(lèi)型的組件,Components組件和Containers組件膨报,兩種組件可能對(duì)應(yīng)于同一頁(yè)面同一部分磷籍,但兩者負(fù)責(zé)的任務(wù)不同适荣,簡(jiǎn)單來(lái)說(shuō)Components組件只負(fù)責(zé)展示,傳遞什么參數(shù)就渲染什么內(nèi)容院领,而Container組件負(fù)責(zé)數(shù)據(jù)流入流出弛矛,決定組件需要什么數(shù)據(jù)和能觸發(fā)什么actions,從某種模型上來(lái)說(shuō)栅盲,Containers或許就是Components外層的一個(gè)包裝汪诉,因此在某些特殊的情況中废恋,可以將Components合并到Containers中去谈秫。
因此對(duì)于Components組件來(lái)說(shuō),所有的數(shù)據(jù)都是通過(guò)組件的屬性props來(lái)決定的鱼鼓。
對(duì)于containers組件來(lái)說(shuō)拟烫,就需要決定哪些state的流入和哪些actions的流出或者說(shuō)是分發(fā)(dispatch),因此也就有了兩個(gè)函數(shù)? mapStateToProps和mapDispatchToProps迄本,mapStateToProps提供兩個(gè)參數(shù)硕淑,一個(gè)是整個(gè)state數(shù)據(jù),另一個(gè)則是原始屬性值Prop嘉赎,它的返回值即是需要映射到組件數(shù)據(jù)(用于渲染頁(yè)面)的state數(shù)據(jù)置媳。
mapDispatchToProps提供一個(gè)dispatch函數(shù)參數(shù),它其實(shí)是store的函數(shù)公条,用于分發(fā)action到reducers中去拇囊。mapDispatchToProp返回值就是一系列的方法,用于映射用戶(hù)對(duì)UI的哪些操作對(duì)應(yīng)需要分發(fā)哪些actions靶橱。
最后需要做的是將容器組件和展示組件綁定起來(lái)寥袭,這時(shí)候需要用到的方法就是react-redux提供的connect方法,connect方法是一個(gè)高階函數(shù)关霸,第一階函數(shù)需要兩個(gè)函數(shù)參數(shù)传黄,其實(shí)就是上面所說(shuō)的那兩個(gè)函數(shù),這兩個(gè)參數(shù)是有順序的队寇,但又不是必須的膘掰,如果不需要傳遞null即可,第二階函數(shù)則需要傳遞這兩個(gè)函數(shù)綁定的組件佳遣,就像上圖那樣把組件裝進(jìn)容器里合并在一起识埋,這樣我們最中需要渲染展示的頁(yè)面是connect后的組件,而不是之前所說(shuō)的展示組件了苍日,因?yàn)閏onnect后的組件才會(huì)有數(shù)據(jù)流的傳遞惭聂,才能享受redux提供的數(shù)據(jù)狀態(tài)循環(huán)流動(dòng)的便利。