REDUX
1.redux究竟是個什么玩意 喳篇?
? 如果要談起redux焊切,我們必須要了解什么叫做 函數(shù)式編程 逻澳,其實我們程序的組件開發(fā)屬于函數(shù)式編程的升級版迷守,函數(shù)式編程帶給我們的優(yōu)勢可以說非常之多,什么功能劃分更容易檩禾,什么維護更簡便挂签,什么高內(nèi)聚低耦合等等優(yōu)勢在此不再贅述,主要談一談函數(shù)式編程的缺點盼产。
1. 函數(shù)式編程容易編程鏈式調(diào)用的模式饵婆。
function foo(){
var a = funA();
var b = funB();
return funC(b);
}
function funA(arg){
return arg + 1;
}
function funB(arg){
return arg + 2;
}
function funC(arg){
return arg + 3;
}
? 類似于這樣的函數(shù)在開發(fā)之中帶給我們的困擾可以說是相當之多了,那么問題來了戏售,我們為什么要用這樣的模式編寫函數(shù)那?
? 因為函數(shù)的作用域是獨立的侨核, 所以我們在函數(shù)之間進行數(shù)據(jù)通訊的時候往往需要通過傳遞參數(shù)
或者使用bind
等方法進行參數(shù)傳遞,這樣的方式帶給我們的就是函數(shù)之間的緊密耦合灌灾,如何進行解耦那搓译,我們需要用到全局變量
進行函數(shù)之間值的傳遞, 可是這樣真的解決問題了么?
? 這樣的做法解決了一個問題锋喜,但是其他問題就會如雨后春筍一般冒出來些己,全局變量浪費內(nèi)存,全局變量不安全嘿般,全局變量.... 段标,辦法總比困難多,對于這樣的數(shù)據(jù)共享我們其實可以使用訂閱發(fā)布模式解決問題炉奴,但是訂閱發(fā)布就萬無一失了么逼庞?
2. 數(shù)據(jù)驅(qū)動模型的實現(xiàn)。
? 對于這樣的需求我們往往需要使用訂閱發(fā)布模式進行實現(xiàn)盆佣,但是訂閱發(fā)布的封裝又出現(xiàn)了n種方案往堡,怎么辦?
? 其實說到這里我們好像知道了一件事共耍,問題的解決方案有了虑灰,但是我們實際上是欠缺一個統(tǒng)一的標準對我們的需求(函數(shù)與函數(shù)或者組件與組件之間的通訊)進行統(tǒng)一,這個標準不一定是最優(yōu)的但是需要應用范圍要廣痹兜。
? 這個時候flux架構(gòu)
出現(xiàn)了穆咐。
2. flux架構(gòu)
? flux架構(gòu)就像是眼鏡,你自然知道什么時候需要他
? flux的橫空出世好像是踏著五彩祥云的至尊寶字旭,拯救萬千前端于水火之中对湃,但是這個至尊寶有點麻煩。
? 這是flux的架構(gòu)圖遗淳,你甚至不需要看懂拍柒,只需要知道整個架構(gòu)的復雜程度還是非常高的,在flux之中想要更改數(shù)據(jù)倉庫(store)屈暗,我們需要調(diào)用dispather拆讯,在dispather之中手動調(diào)用 store之中的set方法,去更改狀態(tài)脂男,我們在開發(fā)企業(yè)級項目的時候,往往會維護一個非常龐大的store种呐,這時候我們面對這樣異常敏感而且不易排錯的功能宰翅,可以說如履薄冰。
? 然后鋼鐵俠替代至尊寶來接你了爽室。
3.redux
? 可以說redux就是flux架構(gòu)的簡化版汁讼,雖然還是很難,但是相對flux而言阔墩,redux把一些易錯的操作進行了內(nèi)部封裝嘿架,這些封裝使得報錯風險急劇下降。
? 比較現(xiàn)成的東西就一定是量身訂造的東西戈擒,雖然redux可以完全獨立使用眶明,可以配合任何框架實現(xiàn)基礎功能但是我們最多的使用redux的地方還是在react之中,為啥那?
? 我們考慮的框架有兩款筐高,vue有比較現(xiàn)成的vuex搜囱, react那, fb的工程師更推薦使用redux柑土,因為redux和react有更高的契合度有更豐富的合作生態(tài)如 react-redux
等蜀肘。
4. redux使用詳解
**part 1 : 看懂一張圖 **
? 這張圖基本說明了使用redux的全部內(nèi)容,但是想要讀懂這張圖可能對于絕大多數(shù)小伙伴來說比較困難稽屏,怎么辦吶扮宠? 不要放棄,我們先學一下基本操作狐榔,過一會再回頭來看這張圖坛增。
-
redux 是干嘛的 ?
一句話解釋 : 其實redux就是用來進行函數(shù)薄腻,組件之間數(shù)據(jù)共享的收捣。
- redux怎樣進行數(shù)據(jù)共享那 ?
一句話解釋 : 就是把一個
對象
放進數(shù)據(jù)倉庫
之中。- redux是否實現(xiàn)了發(fā)布訂閱模式那 庵楷?
一句話解釋 : 實現(xiàn)了罢艾,這是后話。
所以我們大致了解了redux尽纽,那么我們用一個極簡的翻譯來看一下這個圖咐蚯。
?這張圖之中尤其要注意的是創(chuàng)建狀態(tài)
到狀態(tài)區(qū)分處理器
, 這兩個部分之間的綠色箭頭,在通過數(shù)據(jù)倉庫時這個線是虛的弄贿,也就是說春锋,本質(zhì)上來講是狀態(tài)區(qū)分處理器最終將狀態(tài)放入了數(shù)據(jù)倉庫之中,可是為什么這條線要先經(jīng)過數(shù)據(jù)倉庫那 ?
? 敲黑板的重點來了 :
? 創(chuàng)狀態(tài)這個功能其實會創(chuàng)建一個對象差凹,這個對象會被
dispatch
方法直接派發(fā)到 數(shù)據(jù)倉庫之中看疙,但是數(shù)據(jù)倉庫又需要去進行一個狀態(tài)區(qū)分和處理豆拨,這個區(qū)分和處理是被直接集成在數(shù)據(jù)倉庫之中的直奋,相當于倉庫分揀員 , 這個分揀員會自動將創(chuàng)建好的對象進行分類能庆,分類后放入倉庫。
數(shù)據(jù)倉庫內(nèi)部一旦發(fā)生改變了脚线,那么視圖就會發(fā)生相應的改變搁胆,這就是redux完整的流程。
但是這個完整的流程之中有非常之多的注意事項邮绿,如果你已經(jīng)理解了以上的內(nèi)容渠旁,那么就可以繼續(xù)向下學習redux操作實例了。
為了方便操作船逮,我們使用 create-react-app
腳手架工具搭建react環(huán)境顾腊,并使用 redux進行開發(fā) , 編寫redux實例挖胃,同時為了使用的安全和嚴謹杂靶,請務必參考 redux官方文檔,其余野路子博客不建議查看酱鸭。
part 2 : 記得三個單詞
? 1. action 這貨就是我們剛才說的數(shù)據(jù)對象吗垮,這個對象就是JavaScript的單純的對象。 就是下面這樣的
var action = {
name : "一個對象"
}
2. action 還有一些小小的矯情凹髓,就是必須有某些東西烁登,這個東西就叫做 `type`, 我們在創(chuàng)建action的時候通常會創(chuàng)建這樣的一個對象
let action = {
type : MY_FIRST_ACTION,
payload : {
text : "隨便寫一些文本"
}
}
我們寫的這個對象大概就是action了,但是我們想要創(chuàng)建茫茫多個action怎么辦吶 蔚舀? 記得我們有一個創(chuàng)建器就好了饵沧,這個創(chuàng)建器叫做 actionCreater
3. actionCreate長成這樣 , 我們通常定義 action之中type的時候會使用`常量`。
action.js
/*
* 常量定義,這個常量僅代表狀態(tài)赌躺。
*/
export const INCREASE_NUMBER = "INCREASE_NUMBER";
export const REDUCE_NUMBER = "REDUCE_NUMBER";
export const INIT_NUMBER = "INIT_NUMBER";
export function increaseNumber(number){
return {
type : INCREASE_NUMBER,
payload : {
number
}
}
}
export function reduceNumber(number){
return {
type : REDUCE_NUMBER,
payload : {
number
}
}
}
4. 我們要設計一下我們當前state 的數(shù)據(jù)結(jié)構(gòu)狼牺,這個數(shù)據(jù)結(jié)構(gòu)方便我們后續(xù)的操作。
{
calculationNumber :{
type : INIT_NUMBER,
payload : {
number : 0
}
}
}
這大概就是一個及其簡單的數(shù)據(jù)結(jié)構(gòu)了寿谴。
5. 開發(fā)狀態(tài)區(qū)分處理器 reducer
? reducer接受兩個參數(shù) reducer( prevState, state) , 即為原始狀態(tài)和更新狀態(tài) 锁右, 請務必記住reducer的特性,reducer是一個純函數(shù)讶泰,這意味著 同樣的輸入咏瑟,同樣的輸出,如果輸入同樣的內(nèi)容那么輸出一定是一致的痪署,這就是純函數(shù)码泞。 在這里不能調(diào)用 Date.now() ,或者 Math.random() 等方法。
reducer.js
import {
INCREASE_NUMBER,
REDUCE_NUMBER,
INIT_NUMBER
} from "./action"
function calculation(state = initialState , action){
switch(action.type){
case INCREASE_NUMBER :
return Object.assign({},state,{
...action,
payload : {
number : state.payload.number ++
}
});
case REDUCE_NUMBER :
return Object.assign({},state,{
...action,
payload : {
number : state.payload.number --
}
});
default : return state;
}
}
export calculation;
6. 最后我們引入我們的主角
store.getState()
用來獲取store完整數(shù)據(jù)狼犯。
store.subscribe()
用來監(jiān)聽完整數(shù)據(jù)余寥。
import {createStore} from "redux";
import reducer from "./reducer";
let store = createStore(reducer);