❝做者:米卡node
❞
使用過react的同窗應該對Redux這個東西有所瞭解。他是一種「全局狀態管理」的思想(對, 這裏我以爲它是一種思想, 由於對於React來講, 其實Redux內部並無什麼須要與React兼容的東西, react-redux 庫裏纔有), 它信奉的是:react
這其實對咱們是一種約束, 畢竟咱們就算引入了Redux, 也能使用this.props
去進行父子組件數據傳輸, 可是當你須要非父子組件的通訊的時候, 裏面的數據流動會很是難以捉摸, 因此咱們使用Redux。redux
在React中集成Redux時, 在程序的入口處,咱們能夠看到這樣的一段代碼數組
// 這裏的todoApp是一個Reducer函數,接受的是state和actions const store = createStore(todoApp) 複製代碼
在咱們的react使用單一倉庫的時候,能看到一下的一些相似的代碼,從中咱們能看到,咱們本組件的state
是經過this.state = store.getState()
所建立的, 那麼咱們的store
是一個對象,裏面有一個getState
函數可以返回內部的state
,同時這個state
是須要持久保存的,因此咱們大概能有一些思路。markdown
import React, { Component } from 'react' import store from '../../store' import { getIPData } from '../../store/actionCreators' class Page extends Component { // 個人初始化的一個組件,已經可以使用Redux了 constructor(props) { super(props); this.state = store.getState() store.subscribe(this.storeChange.bind(this)); } componentWillMount() { // 獲取IP數據,這裏是做爲一個dispatch的例子 // 值得注意的是getIPData()返回的是一個帶type字段的一個對象。 const action = getIPData(); store.dispatch(action); } render() { return ( <div className="page"> </div> ) } storeChange() { this.setState(store.getState()) } } export default Page 複製代碼
接下來我將本身寫的createStore
函數貼出來, 而後講解。這個函數實現了大部分功能,可是對於中間件的處理這裏並無可以實現,後面我應該會對其有一些補充。閉包
函數
export default function createStore(reducer){ let state = null; const listeners = []; const getState = () => state複製代碼<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">const</span> dispatch = <span class="hljs-function" style="line-height: 26px;">(<span class="hljs-params" style="line-height: 26px;">action</span>) =></span> { state = reducer(state, action) listeners.forEach(<span class="hljs-function" style="line-height: 26px;"><span class="hljs-params" style="line-height: 26px;">listener</span> =></span> listener()) } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">const</span> subscribe = <span class="hljs-function" style="line-height: 26px;">(<span class="hljs-params" style="line-height: 26px;">listener</span>) =></span> listeners.push(listener) <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 這裏初始化dispatch的緣由是在這以前,state是爲null的</span> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">//因此我須要傳一個不存在的action去reducer裏面,拿到最默認的那個defaultState</span> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">//這個defaultState寫在reducer的那個文件裏面</span> dispatch({}); <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> { dispatch, subscribe, getState, } 複製代碼}<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">const</span> dispatch = <span class="hljs-function" style="line-height: 26px;">(<span class="hljs-params" style="line-height: 26px;">action</span>) =></span> { state = reducer(state, action) listeners.forEach(<span class="hljs-function" style="line-height: 26px;"><span class="hljs-params" style="line-height: 26px;">listener</span> =></span> listener()) } <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">const</span> subscribe = <span class="hljs-function" style="line-height: 26px;">(<span class="hljs-params" style="line-height: 26px;">listener</span>) =></span> listeners.push(listener) <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">// 這裏初始化dispatch的緣由是在這以前,state是爲null的</span> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">//因此我須要傳一個不存在的action去reducer裏面,拿到最默認的那個defaultState</span> <span class="hljs-comment" style="color: #5c6370; font-style: italic; line-height: 26px;">//這個defaultState寫在reducer的那個文件裏面</span> dispatch({}); <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> { dispatch, subscribe, getState, } 複製代碼
因此剛纔的分析, 咱們須要建立一個函數對象createStore
oop
一、createStore
裏面用閉包的方法儲存了一個state
,咱們程序用到的倉庫就是這個、還儲存有一個函數數組listeners
,用於儲存用戶定義的函數(通常是用更新後的倉庫重置this.state
),由於我其實有多個頁面都註冊了一個訂閱函數, 因此使用函數數組, 當須要分發時取出來取出來調用便可。this
二、createStore
須要定義一個方法getState
可以拿到state
,這樣就可以在React中使用this.state = store.getState()
來初始化state
並進行讀取了spa
三、createStore
還須要定義一個方法dispatch
, 由於redux不能直接修改state
的值, 因此必須經過dispatch
函數,傳入action
, 而後帶着state
直接傳入reducer
裏, reducer
會傳回修改後的state
。
四、createStore
再須要定義一個方法subscribe
, 這是用來監聽修改的函數, 在使用時, 綁定一個函數, 這個函數裏會在外界得到state
。因此這個函數應該接收一個函數, 而後push入一個隊列裏, 但是應該實時監聽的, 爲什麼要置入隊列呢?這裏個人理解是, 在一開始就將"外界從新得到state"這個函數置入隊列, 相似Promise我承諾會使用這個函數。因此這個函數的使用應該放置在dispatch
裏面, 它傳回一個state
後, 作的事情是將全部隊列中的"外界從新得到state"函數所有拿出來執行一遍。
因此這個createStore
函數的效果很明顯了,getState
用於獲取當前state
, subscribe
用於給外界設置監聽並將監聽函數儲存在createStore
函數的屬性中, 每次用戶經過dispatch
傳action
來修改state
的時候, 將裏面全部的監聽函數拿出來執行一遍。而dispatch
則是用來執行state
修改的, 畢竟這個函數不容許使用setState
這類的函數。
這樣, 咱們就簡單瞭解並分析了Redux的基本原理並對其進行了重寫, 就像我提到的, Redux實際上是一種約束的思想而出現, 這意味着在node中, 咱們一樣也能使用Redux(雖然我以爲可能沒有必要)
本文使用 mdnice 排版