日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Redux源码分析(一)

發(fā)布時(shí)間:2025/3/8 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redux源码分析(一) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Redux源碼分析(createStore)

使用redux都快3年了,到現(xiàn)在也沒認(rèn)真去了解一下源碼罪過啊,所以需要對(duì)它進(jìn)行一些分析和學(xué)習(xí),一方面能更好的去使用它,另一方面也學(xué)習(xí)一下該框架的設(shè)計(jì)思路,首先我們看到 redux/src/index.js 文件

export {createStore,combineReducers,bindActionCreators,applyMiddleware,compose,__DO_NOT_USE__ActionTypes } 復(fù)制代碼

所以主要部分也就是上面幾個(gè)函數(shù),我們下面一點(diǎn)點(diǎn)去分析每一個(gè)功能點(diǎn)


createStore

其實(shí)該文件有著大量的注釋了,大家可以先簡(jiǎn)單的看看代碼中的注釋了解一遍。 其實(shí)createStore就是返回了一個(gè)對(duì)象,這個(gè)對(duì)象只有幾個(gè)方法而已,而我們常用的就是dispatch,subscribe,getState這三個(gè)了

* Creates a Redux store that holds the state tree.* The only way to change the data in the store is to call `dispatch()` on it. 復(fù)制代碼

該函數(shù)的作用呢就是建立一個(gè)store(廢話嘛),那么什么是store呢?我的理解 就是一個(gè)倉(cāng)庫(kù),存著整個(gè)程序的狀態(tài),且只能有一個(gè),就是用這一個(gè)store搞定項(xiàng)目中的全部狀態(tài),當(dāng)然不論多大的項(xiàng)目,統(tǒng)統(tǒng)只有這一個(gè),弄兩個(gè)肯定不好使,并且只有一個(gè)路子去修改里面的數(shù)據(jù),那么就是調(diào)用dispatch()

function createStore(reducer, preloadedState, enhancer) 復(fù)制代碼

可以看到函數(shù)體主要三個(gè)參數(shù),簡(jiǎn)單說下

  • reducer:它是一個(gè)函數(shù)可以表達(dá)為:(preState,action) => newState就是說根據(jù)action和之前的狀態(tài),返回一個(gè)的狀態(tài)(這里的新是新構(gòu)建,而不是修改過,這點(diǎn)切記)
  • preloadedState:字面理解即可,預(yù)先加載的狀態(tài),即初始狀態(tài)
  • enhancer:這個(gè)需要拿出篇幅來說了,增強(qiáng)劑,增強(qiáng)createStore
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {enhancer = preloadedStatepreloadedState = undefined} 復(fù)制代碼

也容易理解,在只有兩個(gè)參數(shù)的情況,并且第二個(gè)為funcion的時(shí)候,那么第二個(gè)參數(shù)就是enhancer了,交互一下參數(shù)位置

if (typeof enhancer !== 'undefined') {if (typeof enhancer !== 'function') {throw new Error('Expected the enhancer to be a function.')}return enhancer(createStore)(reducer, preloadedState)} 復(fù)制代碼

對(duì)enchancer類型判斷,可以看到enhancer就是將store傳入,在內(nèi)部處理之后再將store返回來,繼續(xù)傳入reducer和初始狀態(tài)進(jìn)行構(gòu)建

let currentReducer = reducerlet currentState = preloadedStatelet currentListeners = []let nextListeners = currentListenerslet isDispatching = falsefunction ensureCanMutateNextListeners() {if (nextListeners === currentListeners) {nextListeners = currentListeners.slice()}} 復(fù)制代碼

建立一些變量保存reducer,state,以及訂閱器保存在nextListeners中,ensureCanMutateNextListeners相當(dāng)于每次對(duì)當(dāng)前的訂閱器進(jìn)行備份,因?yàn)槊看斡嗛喴粋€(gè)listener的時(shí)候都是對(duì)nextListeners數(shù)組進(jìn)行添加

function subscribe(listener) {if (typeof listener !== 'function') {throw new Error('Expected the listener to be a function.')}if (isDispatching) {throw new Error('You may not call store.subscribe() while the reducer is executing. ' +'If you would like to be notified after the store has been updated, subscribe from a ' +'component and invoke store.getState() in the callback to access the latest state. ' +'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.')}let isSubscribed = trueensureCanMutateNextListeners()nextListeners.push(listener)return function unsubscribe() {if (!isSubscribed) {return}if (isDispatching) {throw new Error('You may not unsubscribe from a store listener while the reducer is executing. ' +'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.')}isSubscribed = falseensureCanMutateNextListeners()const index = nextListeners.indexOf(listener)nextListeners.splice(index, 1)}} 復(fù)制代碼

訂閱器,注冊(cè)監(jiān)聽函數(shù),每一個(gè)listener都是一個(gè)func,并且返回了一個(gè)取消注冊(cè)監(jiān)聽的函數(shù)unScribe,用于刪除listener,其實(shí)就是將一個(gè)個(gè)的函數(shù)添加到數(shù)組中,之后每次在store發(fā)生變化的時(shí)候(其實(shí)也就是調(diào)用dispatch的時(shí)候)就會(huì)觸發(fā)它~

function dispatch(action) {if (!isPlainObject(action)) {throw new Error('Actions must be plain objects. ' +'Use custom middleware for async actions.')}if (typeof action.type === 'undefined') {throw new Error('Actions may not have an undefined "type" property. ' +'Have you misspelled a constant?')}if (isDispatching) {throw new Error('Reducers may not dispatch actions.')}try {isDispatching = truecurrentState = currentReducer(currentState, action)} finally {isDispatching = false}const listeners = (currentListeners = nextListeners)for (let i = 0; i < listeners.length; i++) {const listener = listeners[i]listener()}return action} 復(fù)制代碼

上面呢就是這里比較重要的dispatch函數(shù)了,其實(shí)非常簡(jiǎn)單,主要就是它:

currentState = currentReducer(currentState, action) 復(fù)制代碼

將當(dāng)前的全部狀態(tài)和action傳入reducer,得到新的state,這樣就完成了state的狀態(tài)更新了,之后再去遍歷全部的listeners,從而在各個(gè)listeners的內(nèi)部去更新view,完成整個(gè)流程(返回值其實(shí)還是這個(gè)action對(duì)象),其實(shí)以上內(nèi)容和三個(gè)函數(shù)應(yīng)該是redux的核心內(nèi)容了,下面用一種簡(jiǎn)單的總結(jié)來表達(dá)一下store(借鑒的阮一峰的)

const createStore = (reducer) => {let state;let listeners = [];const getState = () => state;const dispatch = (action) => {state = reducer(state, action);listeners.forEach(listener => listener());};const subscribe = (listener) => {listeners.push(listener);return () => {listeners = listeners.filter(l => l !== listener);}};dispatch({});return { getState, dispatch, subscribe }; }; 復(fù)制代碼

而該文件還有兩個(gè)函數(shù)分別是

function replaceReducer(nextReducer) function observable() 復(fù)制代碼

第一個(gè)很明顯替換整個(gè)reducer用,在一些熱加載場(chǎng)景應(yīng)該會(huì)用到 而第二個(gè)暫時(shí)還不太理解作者意圖,用觀察者替換訂閱發(fā)布嗎?暫時(shí)先不去想 以上就是整個(gè)createStore的源碼分析~

更多內(nèi)容與討論可以參考我的github.com/jinjiaxing/…

轉(zhuǎn)載于:https://juejin.im/post/5cb946e4f265da038c020f2f

與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的Redux源码分析(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。