什么是redux?
Redux官方文檔對(duì)Redux的定義:Redux是針對(duì)JavaScript應(yīng)用的可預(yù)測(cè)狀態(tài)容器才沧。包含了以下幾個(gè)含義:
1:可預(yù)測(cè)性(predictable): 因?yàn)镽edux用了reducer與純函數(shù)(pure function)的概念民珍,每個(gè)新的state都會(huì)由舊的state建來一個(gè)全新的state。因而所有的狀態(tài)修改都是”可預(yù)測(cè)的”览爵。
2:狀態(tài)容器(state container): state是集中在單一個(gè)對(duì)象樹狀結(jié)構(gòu)下的單一store,store即是應(yīng)用程序領(lǐng)域(app domain)的狀態(tài)集合镇饮。
3:JavaScript應(yīng)用: 這說明Redux并不是單指設(shè)計(jì)給React用的蜓竹,它是獨(dú)立的一個(gè)函數(shù)庫(kù),可通用于各種JavaScript應(yīng)用储藐。
可以讓你構(gòu)建一致化的應(yīng)用俱济,運(yùn)行于不同的環(huán)境(客戶端、服務(wù)器钙勃、原生應(yīng)用)蛛碌,并且易于測(cè)試。不僅于此辖源,它還提供 超爽的開發(fā)體驗(yàn)蔚携,比如有一個(gè)時(shí)間旅行調(diào)試器可以編輯后實(shí)時(shí)預(yù)覽希太。
Redux 除了和?React?一起用外,還支持其它界面庫(kù)酝蜒。 它體小精悍(只有2kB誊辉,包括依賴)。
redux使用場(chǎng)景
典型的Web應(yīng)用程序通常由共享數(shù)據(jù)的多個(gè)UI組件組成亡脑。通常堕澄,多個(gè)組件的任務(wù)是負(fù)責(zé)展示同一對(duì)象的不同屬性。這個(gè)對(duì)象表示可隨時(shí)更改的狀態(tài)霉咨。在多個(gè)組件之間保持狀態(tài)的一致性會(huì)是一場(chǎng)噩夢(mèng)蛙紫,特別是如果有多個(gè)通道用于更新同一個(gè)對(duì)象。
舉個(gè)例子:一個(gè)帶有購(gòu)物車的網(wǎng)站途戒。在頂部惊来,我們用一個(gè)UI組件顯示購(gòu)物車中的商品數(shù)量。我們還可以用另一個(gè)UI組件棺滞,顯示購(gòu)物車中商品的總價(jià)裁蚁。如果用戶點(diǎn)擊添加到購(gòu)物車按鈕,則這兩個(gè)組件應(yīng)立即更新當(dāng)前的數(shù)據(jù)继准。如果用戶從購(gòu)物車中刪除商品枉证、更改數(shù)目、使用優(yōu)惠券或者更改送貨地點(diǎn)移必,則相關(guān)的UI組件都應(yīng)該更新出正確的信息室谚。可以看到崔泵,隨著功能范圍的擴(kuò)大秒赤,一個(gè)簡(jiǎn)單的購(gòu)物車將會(huì)很難保持?jǐn)?shù)據(jù)同步。
Redux框架憎瘸,它可以幫助你以簡(jiǎn)單易用的方式構(gòu)建復(fù)雜項(xiàng)目并進(jìn)行維護(hù)入篮。
redux工作機(jī)制
在Redux中,所有的數(shù)據(jù)(比如state)被保存在一個(gè)被稱為store的容器中 → 在一個(gè)應(yīng)用程序中只能有一個(gè)幌甘。store本質(zhì)上是一個(gè)狀態(tài)樹潮售,保存了所有對(duì)象的狀態(tài)。任何UI組件都可以直接從store訪問特定對(duì)象的狀態(tài)锅风。要通過本地或遠(yuǎn)程組件更改狀態(tài)酥诽,需要分發(fā)一個(gè)action。分發(fā)在這里意味著將可執(zhí)行信息發(fā)送到store皱埠。當(dāng)一個(gè)store接收到一個(gè)action肮帐,它將把這個(gè)action代理給相關(guān)的reducer。reducer是一個(gè)純函數(shù)边器,它可以查看之前的狀態(tài)训枢,執(zhí)行一個(gè)action并且返回一個(gè)新的狀態(tài)托修。
Redux三大核心
Redux的核心由三部分組成:Store,?Action,?Reducer。
Store?: 是個(gè)對(duì)象肮砾,貫穿你整個(gè)應(yīng)用的數(shù)據(jù)都應(yīng)該存儲(chǔ)在這里诀黍。
Action:是個(gè)對(duì)象袋坑,必須包含type這個(gè)屬性仗处,reducer將根據(jù)這個(gè)屬性值來對(duì)store進(jìn)行相應(yīng)的處理。除此之外的屬性枣宫,就是進(jìn)行這個(gè)操作需要的數(shù)據(jù)婆誓。
Reducer: 是個(gè)函數(shù)。接受兩個(gè)參數(shù):要修改的數(shù)據(jù)(state) 和?action對(duì)象也颤。根據(jù)action.type來決定采用的操作洋幻,對(duì)state進(jìn)行修改,最后返回新的state翅娶。
store
我們通過redux提供的createStore這個(gè)方法來創(chuàng)建一個(gè)Store文留。它接受對(duì)store進(jìn)行處理的reducer作為參數(shù)。
Store有三個(gè)方法:
getState:用來獲取store里面存儲(chǔ)的數(shù)據(jù)竭沫。
dispatch:?store里的數(shù)據(jù)不能直接修改燥翅,只能通過觸發(fā)action來進(jìn)行修改,這個(gè)方法就是用來觸發(fā)action蜕提。
subscibe:訂閱store改變時(shí)森书,要進(jìn)行的操作。比如在react中谎势,當(dāng)store改變時(shí)凛膏,我們需要調(diào)用render方法對(duì)視圖進(jìn)行更新
Reducer
我們可以將對(duì)store的操作,寫在一個(gè)reducer中脏榆,比如:
可以看到這個(gè)reducer對(duì)store的visibilityFilter和todos的兩部分?jǐn)?shù)據(jù)進(jìn)行了處理猖毫。隨著應(yīng)用的復(fù)雜,如果我們把對(duì)所有數(shù)據(jù)的處理须喂,都寫在一個(gè)reducer中鄙麦,那么它會(huì)變得很冗雜。如果我們將對(duì)每一部分的數(shù)據(jù)的處理镊折,寫在一個(gè)單獨(dú)的reducer中胯府,它接受該部分的數(shù)據(jù)作為state。那么整個(gè)reducer會(huì)變得整潔和清晰恨胚。
因此骂因,redux為我們提供了combineReducer這個(gè)API,幫助我們分開書寫reducer赃泡, 并且最終把這些reducer給集合到一個(gè)根reducer中寒波。
react-redux
如果我們需要在react當(dāng)中運(yùn)用它乘盼,那么我們需要手動(dòng)訂閱store的狀態(tài)變化,來對(duì)我們的react組件進(jìn)行更新俄烁。那么react-reudx這個(gè)工具绸栅,就幫我們實(shí)現(xiàn)了這個(gè)功能,我們只需對(duì)store進(jìn)行處理页屠,react組件就會(huì)有相應(yīng)的變化粹胯。
所以當(dāng)我們?cè)趓eact項(xiàng)目當(dāng)中應(yīng)用redux時(shí)需安裝:
npm install --save redux
npm install --save react-redux
兩者關(guān)系圖為如下
這個(gè)工具主要提供兩個(gè)API:
connect
現(xiàn)在我們有了store,那么我們?cè)趺床拍茉谖覀兊慕M件中對(duì)它們進(jìn)行操作呢辰企?connect就為提供了這個(gè)功能风纠。它接受mapStateToProps,?mapDispatchToProps等作為參數(shù)。比如在我的TodoList這個(gè)組件中需要用到todos這部分?jǐn)?shù)據(jù)牢贸,那么我完善mapStateToProps這個(gè)函數(shù)竹观,它接受store中的state作為參數(shù),返回一個(gè)對(duì)象潜索,屬性就是state中我們需要的數(shù)據(jù):
mapStateToProps就將我們的state轉(zhuǎn)換為了props對(duì)象臭增。
同樣的,我們可能需要在組件中對(duì)state進(jìn)行處理竹习。mapDispatchToProps就是幫助我們?cè)诮M件中通過props調(diào)用dispatch來觸發(fā)action的:
最后我們調(diào)用connect這個(gè)方法誊抛,將mapStateToProps,?mapDispatchToProps生成的props注入到需要使用它的組中:
這樣由驹,我們?cè)赥odoList這個(gè)組件中芍锚,就能直接通過props.todos獲取到todos中的數(shù)據(jù), 通過props.onTodoClick對(duì)todos進(jìn)行處理蔓榄。
provider
上面我們調(diào)用connect時(shí)并炮,在mapStateToProps?和?mapDispatchToProps我們分別用到了store的state和dispatch。但是在組件中的store是哪里憑空冒出來的呢甥郑?
provider就是來解決這個(gè)事的逃魄。Provider使它的子孫在調(diào)用connect方法時(shí),都能獲取到store澜搅。
這樣伍俘,Provider的子孫組件都能在調(diào)用connect時(shí)獲取到store。
總結(jié):
Redux:?store,?action,?reducer
store:?getState,?dispatch,?subscribe
combineReducers
createStore
store????dispatch????action????reducer
react-redux:
connect: 將store作為props注入
Provider: 使store在子孫組件的connect中能夠獲取到勉躺。