示例代碼地址在這裏 ,你能夠經過git clone
命令clone到本地,也能夠直接下載。javascript
而後經過執行npm install
安裝所依賴的模塊 。以後即可以經過node
執行示例代碼。java
隨着 JavaScript 單頁應用開發日趨複雜,JavaScript 須要管理比任什麼時候候都要多的 state (狀態)。 這些 state 可能包括服務器響應、緩存數據、本地生成還沒有持久化到服務器的數據,也包括 UI 狀態,如激活的路由,被選中的標籤,是否顯示加載動效或者分頁器等等。node
簡單來講Redux
就是javaScript
的狀態管理器。同時,Redux
支持React
、Angular
、Ember
、jQuery
等。ios
到這裏你可能並不知道該如何使用Redux
,彆着急,在瞭解如何使用以前,須要先理解相關的基本概念。示例代碼可查看demo1/app.js
git
在一個能夠進行用戶交互的界面上,當咱們觸發了交互事件的時候,界面也會跟着進行更新。例如在一個app中的下拉刷新,當咱們進行下拉刷新這個動做時,會去請求服務器數據,當返回結果時app的頁面會更新。界面的改變咱們就能夠看作是狀態的變化。而狀態的變化是因爲咱們進行了某個動做。在Redux中,尤爲須要注意的是State是隻讀的,且狀態的變化只能經過Reducer函數進行轉換,es6
Action就是你與界面進行交互的行爲。它是一個對象且必需要包含一個type
屬性,用來描述你要作的是什麼事。github
Store
就是應用狀態的容器。用來維護應用的state
、獲取state
、更新state
、監聽state
變化等。這裏須要注意的是整個應用只有一個Store
web
一個純函數,接收當前的state
和一個action
參數,根據當前的行爲,即action
的type
屬性返回一個新的state
。狀態的更新只能經過這個函數。shell
可能看了上述內容你仍然不知道什麼是Redux
,Redux
能幹什麼。下面結合實例demo1/app.js
中的內容理解上述概念。npm
1.引入相關模塊(這裏沒有使用ES6
的方式是爲了能使用node
命令直接查看結果,node
命令沒法識別import
。固然你也能夠經過配置babel
的方式使用import
語法)
var { createStore } = require('redux'); //import { createStore } from 'redux' //es6方式引入
2.定義Reducer
,來進行狀態的更新
var defaultState = 'JavaScript' function programLanguage(state = defaultState, action) { switch (action.type) { case 'IOS': return action.language; case 'WEB': return action.language; case 'SNACK': return action.language; default: return state; } }
從上述代碼能夠看到,咱們定義了一個programLanguage
方法,其實這就是一個Reducer
,它接受了當前state
和action
參數。用來更新state
。
3.建立store
。
let store = createStore(programLanguage);
再次強調整個應用中只能有一個store
,即createStore
函數只能被調用一次。
createStore
的定義以下:
function createStore(reducer, preloadedState, enhancer);
能夠看到的是createStore接受三個參數
reducer:就是上述的reducer函數,這裏再也不贅述
preloadedState: 初始state
enhancer:組合store creator的高級函數,返回一個新的強化過的store creator。
4.更改應用的狀態
store.dispatch({ type: 'default' }); store.dispatch({ language: 'Swift', type: 'IOS' }); store.dispatch({ language: 'Ruby', type: 'WEB' }); store.dispatch({ language: 'Python', type: 'SNACK' });
經過dispatch
方法將action
發送到reducer
函數中,進行狀態的更新。
執行node demo1/app.js
的打印結果以下
JavaScript JavaScript Swift JavaScript Swift Ruby JavaScript Swift Ruby Python
當執行第一句代碼store.dispatch({ type: 'default' });
時 返回的是JavaScript。是因爲dispatch方法內部會調用在createStore
中註冊的Reducer
函數,即programLanguage
函數。由programLanguage
的內部邏輯return
的是一個defaultState
。此時整個應用的狀態爲JavaScript
當執行第二句代碼store.dispatch({ language: 'Swift', type: 'IOS' });
時 返回了JavaScript Swift
。是因爲type
爲IOS
,programLanguage
返回的是state + ' ' +action.language;
由於上一句代碼將應用的狀態變爲了JavaScript
,因此結果天然就是JavaScript Swift
。同時整個應用的狀態也會變成JavaScript Swift
。
同理,第三句和第四句代碼也是如此。
5.訂閱狀態的更新
store.subscribe(() => console.log(store.getState()) );
爲了方便查看狀態的變化。這裏調用了subscribe
方法,每當狀態發生變化時都會調用其回調函數。
store.getState()
獲取應用的當前狀態。
隨着頁面的增長,Action
必然也會愈來愈多,若是Action
內部所攜帶的消息也不少。此時若是須要狀態的更新,就須要寫複雜的Action
,形成代碼可讀性差,文件臃腫。因此咱們可使用Action creator
來構造Action
。當須要進行狀態更新就傳入相應的數據到Action creator
中生成Action
並返回。
在demo2
中
咱們建立了一個HomeAction
的文件專門用來存放Action Creator
。在此文件中咱們建立了三個Action creator
,分別是action_ios
、action_web
、action_snack
,並將建立Action
的任務交給這三個函數。
與此同時在咱們demo2/app.js
中須要dispatch
一個action
的時候。只須要從Action creator
中取出Action
就好了。並不須要咱們手動的去建立,如此一來便大大增長代碼的可讀性,可維護性。
一樣的隨着業務量的增長,Reducer
一定也會愈來愈大。因此咱們能夠按模塊的不一樣來拆分Reducer。將一個大的Reducer
拆分紅幾個小的reducer
。
在demo3
中reducer
文件夾中,咱們按照模塊的不一樣的拆分homeReducer
和profileReducer
。分別用來處理home
頁面和profile
頁面狀態的更新。
那麼問題來了,這麼拆分如何使用createStore
去建立store
呢,畢竟createStore
只能傳一個Reducer
參數。並且createStore
只能調用一次。
彆着急,在redux
中提供了一個combineReducers
的方法,用來組合咱們的Reducer
。
const mainReducer = combineReducers({ homeReducer, profileReducer }) let store = createStore(mainReducer);
謝謝閱讀,若是感受本文對你有用,那將是個人榮幸。若是有寫的錯誤的地方也請留言指正。