[TOC]html
之前沒怎麼寫過技術類的文章,對於技術不少時候是現用現學,這樣一般能解決遇到過的絕大多數問題,但也帶來了一個弊端,那就是僅停留於解決問題的層面,而忽略了對技術背後的設計思想和設計理念進行深刻的研究。雖然技術的發展突飛猛進,但那些終歸只是由設計思想演繹出來的玩物,若是隻是不斷的去學習演繹出來的東西,而忽略了對思想的研究,就終究會陷入舍本逐末的惡性循環。react
技術的提升離不開實踐,實踐有助於深化對技術的理解,但若是隻實踐而不加以總結的話也容易陷入只見樹木不見森林的迷途。若是說實踐是戰術上的肉搏,那總結就是戰略上的提煉,高屋建瓴,將實踐中的精髓抽取出來,以達到去繁入簡、返璞歸真的境界。 鑑於此,也就打算把學習、實踐過的技術進行再次的學習、總結,並以博文的形式記錄下來,這樣一方面有助於理清思路,創建知識體系,另外一方面更有助於深刻對技術的理解和掌握,這也是我打算開始寫技術文章的初衷。 redux
redux是一個庫,用於管理狀態,也能夠說是一個容器,這個容器裏容納了各類須要的狀態信息,並對外提供了一些方法來管理這些狀態。目前redux更多的實踐是和react結合,管理react的視圖狀態,但它也能夠獨立看成發佈、訂閱系統來使用。總之這些只是概念層面上的東西,實踐完以後再來看概念就會容易理解,不然概念永遠是模糊的。api
redux有三大設計哲學: 一、單一數據源。 顧名思義就是全部的狀態信息都存儲在同一個容器裏。 二、狀態是隻讀的。 redux是用來管理狀態的,居然能管理,那就包含了對狀態的增、刪、改操做。這裏的只讀是指新狀態不會破壞原來的舊狀態,也就是說新狀態的產生過程是:一、先從舊狀態進行深拷貝獲得一個複本。二、對複本進行操做獲得新狀態。 三、使用純函數來更新狀態。 純函數是指輸入相同的參數時,總能獲得相同的輸出結果,而且不會修改輸入的參數。數組
這三大設計哲學主要是爲了簡化對狀態的管理,讓狀態可預測、可追蹤,從而易於維護代碼,也更易於排查bug。數據結構
redux的工做流以下圖所示:異步
https://slides.com/jenyaterpil/redux-from-twitter-hype-to-production#/9ide
redux是管理狀態的,全部的狀態都存儲在「store」裏,因此store是一個數據中心,也是最核心的要素。同時store對外暴露了一些api用於管理store裏的數據,這些api包括getState、dispatch、subscribe、replaceReducer。store是由createStore函數建立的,如:函數
const store = createStore(reducer, preloadedState, enhancer)
createStore的實現原理以下:工具
const createStore = reducer => { let state; // listeners用來存儲全部的監聽函數 let listeners = []; const getState = () => state; const dispatch = action => { state = reducer(state, action); // 每一次狀態更新後,都須要調用listeners數組中的每個監聽函數 listeners.forEach(listener => listener()); } const subscribe = listener => { // subscribe可能會被調用多交,每一次調用時,都將相關的監聽函數存入listeners數組中 listeners.push(listener); // 返回一個函數,進行取消訂閱 return () => { listeners = listeners.filter(item => item !== listener); } } return { getState, dispatch, subscribe }; }
dispatch用來派發一個action,全部對state的更新以及獲取數據都是經過派發一個action來完成的。如:
let action1 = { type: 'READ_BOOK', data: { book: 'book1' } }; store.dispatch(action1);
getState用於獲取store裏的狀態數據,即state。如:
let state = store.getState();
subscribe用於訂閱store裏的數據狀態,當store裏state數據變動時,通知訂閱方。如:
const render = () => { ... } store.subscribe(render);
這個通常開發用不到。
action是指一個操做動做,當須要操做store裏的數據時,就須要分發一個action來通知store。每一個action描述了一個操做,它是一個object的數據結構,有一個必填屬性「type」,值是字符串常量,用於標識動做,能夠理解爲動做的ID,另外action對象裏還能夠攜帶其餘數據信息,這要根據action所要完成的操做來定。
reducer是用來響應action來處理狀態的,它會對每一個分發的action進行操做,根據傳過來的action和store裏已有的sate值進行一些運算,而後返回新的state。
actionCreator是一個相似於工廠模式的生產工具,用於生產action。如:
const learnReduxActionFactory = book => { type: 'READ_REDUX_BOOK', book }
combineReducers是Redux提供的一個工具函數,能夠把多個拆分的reducer合併成一完整的reducer。 例如在頁面狀態中存儲三種數據狀態,分別爲data一、data2和data3, 它們是相互獨立的。如:
state = { data1: { ... }, data2: { ... }, data3: { ... } };
一樣咱們把處理這三種數據狀態的reducer函數也拆分紅三個小的reducer,分別爲reducer一、reducer2和reducer3。以下:
const reducer1 = (previousState= {}, action) => { // 根據action和state.data1計算產生新的state.data1 return state.data1; }; const reducer2 = (previousState= {}, action) => { // 根據action和state.data2計算產生新的state.data2 return state.data2; } const reducer3 = (previousState= {}, action) => { // 根據action和state.data3計算產生新的state.data3 return state.data3; }
最後利用combineReducer將這三個子reducer函數合併成一個完整的reducer並返回。以下:
const { combineReducers } = Redux; const finalReducer = combineReducers({ data1: reducer1, data2: reducer2, data3: reducer3 });
在ES6開發環境下,經常使用的作法是令子reducer函數名稱和數據狀態的命名保持一致,即將reducer一、reducer二、reducer3分別命名爲data一、data二、data3。即:
const finalReducer = combineReducers({ data1: data1, data2: data2, data3: data3 });
也能夠簡寫爲:
const finalReducer = combineReducers({data1, data2, data3});
平常開發中,一般會將大的reducer拆分紅多個小的reducer進行單獨維護,這樣的分治能提升維護效率。
redux中間件提供的是位於action被派發以後,到達reducer以前的擴展點,所以能夠利用redux中間件來完成日誌記錄、調用異步接口或者路由等。redux中間件的做用主要有兩個: 一、截獲action 二、發出action redux中間件異步請求的工做流以下圖所示:
https://slides.com/jenyaterpil/redux-from-twitter-hype-to-production#/23
redux既能夠做爲發佈訂閱系統獨立使用,也能夠和react結合來管理react組件的狀態。目前最多見的使用場景是與react結合,讓react組件間通訊更加容易。另外經過使用豐富的redux中間件,能擴展系統的特性。
原文出處:https://www.cnblogs.com/anlewo/p/10328201.html