學習Redux刷新了我的前端App狀態管理觀
寫在前面的話
聽過Redux好久了,不過真的開始學大概在一個月前,學會Redux之后我用一周多的時間重構了之前純React寫的一個小項目。學習的過程中心態變化很大,但是最終真的感覺如果再寫復雜一點的項目,我應該再也不會直接用state管理所有狀態了。Redux真的刷新了我的狀態管理觀。
本文的寫作目的在于讓那些一直在使用React,但是還沒有使用Redux管理復雜應用狀態的同學了解Redux的核心思想并能夠更加平滑的學習使用Redux。
為什么要使用Redux
快雙十一了,突然想到一個比喻來解釋為什么會有React這類框架的存在,為什么我們要使用Redux,話說以前使用jQuery不也挺快樂的嘛。
一個比喻
想想現代物流系統發展的不同階段,我們寄一件東西的過程,
-
沒有物流系統時:
-
打包準備好要送出去的東西;
-
出門乘車到達朋友家,把東西送給朋友;
-
很直接很方便,很費時間,送東西的距離有限(同城?);
-
-
出現了各大物流公司時:
-
打包準備好要送出去的東西;
-
出門到距離家最近的物流公司,填寫物品,收件人等基本信息;
-
物流公司替你送物品到你的朋友處,自己可以回家做別的事情了;
-
多了一個中介,要付一定的運送成本,但是東西可以送到遠在幾千公里之外的其它人了,用一點點錢節約了自己寶貴的時間,完成了以前我們不可能做的事情;
</ul> </li>
</ul>
-
API State;(數據)
-
UI State;(UI的表現形式)
-
中古
-
jQuery 時期
-
我們使用諸如 $(element).addClass('active') 這樣的語句來改變狀態;
-
對簡單的應用來說,這樣寫簡單明了,但是狀態一多一復雜就亂了,并不存在一個專門管理狀態的地方;
-
-
近代
-
React內部管理狀態時期
-
我們引入了 state 來管理組件狀態,界面想顯示不同的樣子,我們通過各種函數來改變 state 來實現
-
已經存在一個專門管理狀態的 state (對象,數組)了,對大部分應用來說,用 state 來管理狀態已經足夠了,但是應用復雜了會使得狀態
</ul> </li>
-
現代
-
引入Redux等狀態管理機制時期;
-
redux使用一個 store 來全局管理各種狀態,提供一些不算復雜的api來專門管理狀態;
-
可以管理更加復雜的狀態,通過redux的管理,狀態的改變變得更加清晰,可預測, redux 中的狀態是一個只讀屬性,通過一定的方法,可以回到已經經歷過的某個狀態(時間旅行);
</ul> </li>
</ul>
-
為改變已有的狀態提供了方案;
-
為異步獲取新的數據提供了方案;
-
React(Redux是flux架構的實現,雖然其也可以配合其它框架使用,但是它和React可能還是更配一些吧);
-
基礎的ES6知識(Redux重視函數式編程,會使得編程的結構看起來更加簡潔);
-
用了ES6(甚至ES7)當然免不了要學習使用Webpack,Babel等;
-
還有一點,我覺得學習編程應該不怕折騰,使用Redux管理一個狀態可能需要改好幾個文件里的代碼才能實現,編程不再顯得那么直接(比如 通過 connect.js 調用 action.js 里的某個 action ,并依據這個 action 觸發 reducer.js 里面的某個 reducer 函數依據現有的 state ,創建一個新的 state ),redux把一些操作給抽象化了,如果思維沒有跟著改變,會讓人有一種redux文檔里面的東西我都看懂了,但是我怎么就是編不出來呢?那種痛苦的感覺。
-
state :app中的狀態存放的地方,并且state是只讀的,不同于React,Redux中state的更改,其實是創建了一個全新的state;
-
action :是一個對象,作用和他的名字一樣,用來表明,你想要做的那件事情,該對象的屬性type,用來標記,你要做的事情;
-
reducer :是一個函數,接收當前state,和一個action作為參數,依據action基于當前的 state 生成新的 state ;
-
dispatch :推送某個 action 給 reducer ;
-
action creater :一個創建 action 的函數,返回一個 action 對象;
-
異步action :返回一個函數,和中間件配合可以很容易的實現異步操作;
-
store :可以理解為 state 的家,全局只有一個,有以下方法
-
getState() :獲取當前的state樹;
-
dispatch(action) :觸發一個action,創建state;
-
subscribe(listener) :
-
replaceReducer(nextReducer)
-
-
combineRedecers(reducers) :當我們的應用比較復雜的時候,我們可能會分開寫好幾個 reducer ,這個函數的作用就是把這些單獨的reduce合并為一個大的reduce,需要注意的是我們的state的結構和我們的各個 reducer 是一一對應的。
-
applyMiddleware(...middlewares) :告訴redux我們會用到那些中間件,比如說要用到基礎的異步,我們會用到thunk中間件;
</ul>
Redux是怎么管理狀態的
上面已經說了Redux管理狀態特別好,那Redux究竟是如何管理狀態的呢?狀態分為UI State 和 API State,Redux針對這兩部分也提供了兩種方法
Redux的數據流
還是用圖片來說明更加清楚
下圖說明了Redux和React的狀態流分別是怎么樣的;
下圖說明了使用Redux管理狀態為什么是可預測的
Redux的數據是如何流動的其實也是理解Redux的好處的關鍵部分之一,簡單來說每個事件會發送一個action,action通過dispatch觸發reduce,直接依據舊的state生成一個新state替代最頂層的store里面原有的state。
說了這么多使用redux管理狀態的好處,但是你看到這里可能依舊不知道如何使用 redux ,不要著急,我和你分享我的Redux學習經驗。
開始學習Redux
學習Redux前需要了解的基礎知識
如果你已經能很熟練的使用React,我覺得學習Redux需要了解的基礎知識,你應該都已經了解了。具體說來主要有以下內容;
學習使用Redux
網上關于Redux的教程特別多了( 官方文檔 寫的特別好),學習新概念是比較惱人的一個過程,所以我還是會對Redux提供的api做一個簡潔的描述,然后我會把我這段時間看過的我覺得比較好的文章的鏈接放在下面以供大家參考。
Redux中的一些概念
let store = createStore( comReducer, applyMiddleware(thunk) );
-
bindActionCreators(actionCreators, dispatch) :綁定 actionCreator 和 dispatch 以供直接使用;
配合 React 使用Redux需要掌握的一些概念
redux只是管理狀態的一種方法,真的用在React里,使用作者提供的一個工具 react-redux 會更加方便,其api很簡單,主要有以下幾個;
-
<Provider store> ,嵌套在React組件的最外層,因此可以把state傳給所有的組件(利用了React的 context );
-
把React組件分為容器組件和UI組件兩類,容器組件管理邏輯,UI組件管理顯示效果二者通過 connect 方法連接,容器組件一般由UI組件依據 connect 生成;
-
mapStateToProps() ,存在于容器組件中,針對UI組件的各狀態(依據 state ,或者父組件的 props )生成;
-
mapDispatchToProps() ,存在于容器組件中,針對UI組件中的各可能改變state的事件定義的一系列的函數,依據 props 傳給UI組件;
Redux參考文獻
Redux還有一個非常酷的工具,讓我們可以實時看到當前的state,使用redux不可不用啊。
學會使用還是得靠實踐
在弄懂了一些關鍵的核心概念以后,如果還是不知道怎么寫,就模仿官方給的多個例子針對自己的需求敲寫一次吧。模仿了兩個例子就肯定明白了。
后言
Redux也有自己的 小生態 ,理解的一些技術輔助Redux更加方便的實現狀態管理,其中有一些是下一步我特別想了解的比如說 immutable-js , reselect , normalizr ,當然因為學習了Redux,所以我也想對函數式編程做進一步理解,之前找到了一本非常好的關于函數式編程的書 mostly-adequate-guide ,分享給大家,大家一起學習。
來自:https://segmentfault.com/a/1190000007397551
-
-
沒錯,沒有物流系統時對應的就是以前使用jQuery的前端階段,做一件事情很直接,如果只是送快遞給一個特別近的人,那當然是非常方便。就算你要從北京送一個東西到上海,在這個階段你也可以實現,但是需要付出的代價就太大了。
而出現了各大物流公司對應的就是使用React等框架的階段,學習React需要付出成本,如果你只需要做簡單的事情(比如說你想把東西送給你的鄰居),那使用此類框架其實顯得特別累贅,把簡單的事情復雜化了,但是如果你想做復雜一點的事情(同時寄禮物給三個不同城市的人),那么選擇快遞公司是不會錯的。
那么React和Redux的關系又該如何理解呢?
我覺得我們可以把 React 比如為一家自建快遞系統的公司(京東?),在一定范圍內,它的快遞系統已經足夠好了(部分一二線城市一天內直達),但是要管理這個日益復雜的快遞系統,需要公司付出巨大的成本。
Redux 可以看做業內最好的第三方快遞系統(順豐?),使用它比較貴(學習成本稍微有點高),但是他到達全國主要城市都會特別快,如果你是一個電商老板,采用這個第三方物流系統之后,你只需要關注于自己的貨物,幾乎不用再去關心物流怎么辦了。
不同于順豐每一次寄貨都要那么高的價格,redux是一個學習一次,就可以免費寄貨的優秀第三方快遞系統,那我們當然要解散自己的物流公司來采用這個第三方的選擇的。不過話說回來,學習是需要有成本的,所以是直接使用React還是學習Redux再使用,這是你一個你需要依據你自己項目的實際情況作出選擇的事情。
不過這個例子可能并不足夠合適,Redux做的不僅僅是管理原來React里state里面的狀態。Redux其實可以接管我們的app里所有的數據。接下來我們具體看看Redux究竟做了什么。
Redux可以做什么
我們常常聽到一種說法,“Redux是一個非常好的狀態管理器”,那究竟什么是狀態呢。
重新理解前端中的狀態
想想我們平時看的網頁,app,或者任何其它和我們有交互的東西,我們感覺到交互的發生是因為界面依據我們的行為作出了反饋,界面所有的改變,其實都可以看作是狀態的改變,或者說界面會改變是因為我們的某個行為(事件)( click , drag , move ...)觸發了某個函數,函數造成了狀態的改變,進而改變了界面。
如此看來,無論是顯示隱藏這種可見的狀態,還是從服務器獲取更多的數據,這些都可以看做是狀態,而這些狀態就是我們的Redux要管理的。
換一個可能比較專業一點的說法吧,狀態包括
前端狀態管理史
為了更好的展示Redux的好,我們回顧一下前端的狀態管理史(稱為史其實并不合適,以下三種模式現在都有大量人在使用)。
-