摘要:只有在你需要實(shí)現(xiàn)代碼分隔,而且需要立即加載一些的時(shí)候才可能會(huì)用到它。
import isPlainObject from "lodash/isPlainObject" import $$observable from "symbol-observable" /** * These are private action types reserved by Redux. * For any unknown actions, you must return the current state. * If the current state is undefined, you must return the initial state. * Do not reference these action types directly in your code. * * 這些都是redux本身預(yù)置的私有action types * 對(duì)于任何未知的action, 你一定要return當(dāng)前的state. * 如果當(dāng)前的state是undefined, 你一定要return最初始的state. * 一定,一定,一定不要在代碼中直接引用action types . */ export const ActionTypes = { //初始化action的type,沒(méi)有action參數(shù)的時(shí)候用 INIT: "@@redux/INIT" } /** * 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. * There should only be a single store in your app. To specify how different * parts of the state tree respond to actions, you may combine several reducers * into a single reducer function by using `combineReducers`. * * 創(chuàng)建一個(gè)包含state tree(狀態(tài)樹(shù))的redux store. * 唯一改變store中data(數(shù)據(jù))的方法是調(diào)用`dispatch()`方法. * 在你的程序中應(yīng)該只存在唯一一個(gè)store, 來(lái)表明state tree各部分怎樣對(duì)action做出反應(yīng) * 你可能需要將多個(gè)reducer用`combineReducers`組合在一起 * * @param {Function} reducer A function that returns the next state tree, given * the current state tree and the action to handle. * * @param {Function} reducer 參數(shù)reducer是一個(gè)返回下一個(gè)state tree(狀態(tài)樹(shù))的函數(shù),來(lái)操作當(dāng)前的state和action * * @param {any} [preloadedState] The initial state. You may optionally specify it * to hydrate the state from the server in universal apps, or to restore a * previously serialized user session. * If you use `combineReducers` to produce the root reducer function, this must be * an object with the same shape as `combineReducers` keys. * * @param {any} [preloadedState] 初始化的state,可選參數(shù),你可以在universal(一般的,普遍的,我不知道怎么說(shuō)比較合適) * 的程序中與服務(wù)器的state結(jié)合,或者restore一個(gè)預(yù)先連續(xù)的user session(直譯過(guò)來(lái)的,一般用不到) * 如果你用`combineReducers`產(chǎn)生一個(gè)根reducer函數(shù),這一定是一個(gè)和`combineReducers`的key一樣的對(duì)象(根reducer是一個(gè)對(duì)象) * * @param {Function} [enhancer] The store enhancer. You may optionally specify it * to enhance the store with third-party capabilities such as middleware, * time travel, persistence, etc. The only store enhancer that ships with Redux * is `applyMiddleware()`. * * @param {Function} [enhancer] store增強(qiáng)器. 可選參數(shù).用來(lái)增強(qiáng)第三方庫(kù)的能力集(這個(gè)詞是直譯), * 比如中間件,時(shí)空穿越,和持續(xù)性(也是直譯).redux的store增強(qiáng)器是`applyMiddleware()` * * @returns {Store} A Redux store that lets you read the state, dispatch actions * and subscribe to changes. * * @returns {Store} 返回值 一個(gè)redux的store,讓你可以讀取state, dispatch actions 和訂閱更改 */ //createStore的目的只是創(chuàng)建一個(gè)store,這個(gè)store包含5個(gè)方法(一般只用到3個(gè),最常用的是dispatch) export default function createStore(reducer, preloadedState, enhancer) { if (typeof preloadedState === "function" && typeof enhancer === "undefined") { enhancer = preloadedState preloadedState = undefined } if (typeof enhancer !== "undefined") { if (typeof enhancer !== "function") { throw new Error("Expected the enhancer to be a function.")//期望enhancer是個(gè)函數(shù) } // 當(dāng)enhancer是函數(shù)的時(shí)候返回,然后執(zhí)行,并將createStore作為參數(shù)傳入,然后createStore就在enhancer里面 //去執(zhí)行了 return enhancer(createStore)(reducer, preloadedState) } if (typeof reducer !== "function") { throw new Error("Expected the reducer to be a function.") } let currentReducer = reducer //一般此reducer不是單個(gè)的reducer函數(shù),而是combineReducers函數(shù) let currentState = preloadedState let currentListeners = [] //監(jiān)聽(tīng)函數(shù) let nextListeners = currentListeners let isDispatching = false function ensureCanMutateNextListeners() { //nextListeners不是currentListeners if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } /** * Reads the state tree managed by the store. * * 讀取被store管理的state樹(shù) * * @returns {any} The current state tree of your application. * *返回你的程序的當(dāng)前的state樹(shù) */ function getState() { return currentState } /** * Adds a change listener. It will be called any time an action is dispatched, * and some part of the state tree may potentially have changed. You may then * call `getState()` to read the current state tree inside the callback. * * 添加一個(gè)改變事件,任何時(shí)候一個(gè)action被dispatch這個(gè)事件就會(huì)被調(diào)用,然后state樹(shù)的某一部分就 * 會(huì)改變. 你也可以在回調(diào)函數(shù)里面調(diào)用`getState()`來(lái)查看當(dāng)前的state樹(shù) * * You may call `dispatch()` from a change listener, with the following * caveats: * * 以下幾種情況你也可以調(diào)用`dispatch()` * * 1. The subscriptions are snapshotted just before every `dispatch()` call. * If you subscribe or unsubscribe while the listeners are being invoked, this * will not have any effect on the `dispatch()` that is currently in progress. * However, the next `dispatch()` call, whether nested or not, will use a more * recent snapshot of the subscription list. * * 每次調(diào)用`dispatch`之前,訂閱都會(huì)被snapshot, * 當(dāng)事件被觸發(fā)的時(shí)候你訂閱或者不訂閱,在當(dāng)前的進(jìn)程中都不會(huì)對(duì)`dispatch`有什么影響 * 然而當(dāng)下一次`dispatch`被調(diào)用時(shí),無(wú)論嵌套與否,將會(huì)使用最近的訂閱列表的snapshot * * 2. The listener should not expect to see all state changes, as the state * might have been updated multiple times during a nested `dispatch()` before * the listener is called. It is, however, guaranteed that all subscribers * registered before the `dispatch()` started will be called with the latest * state by the time it exits. * * 不要期待監(jiān)聽(tīng)事件可以看到所有的狀態(tài)改變,因?yàn)樵谑录徽{(diào)用前,state在嵌套的`dispatch`間 * 可能已經(jīng)更新了很多次 * * @param {Function} listener A callback to be invoked on every dispatch. * 每次dispatch都會(huì)被出發(fā)的回調(diào)函數(shù) * * @returns {Function} A function to remove this change listener. * 返回一個(gè)移除該事件的函數(shù) */ function subscribe(listener) { if (typeof listener !== "function") { throw new Error("Expected listener to be a function.") } let isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) //添加事件到nextListeners數(shù)組 return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() const index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) //從nextListeners數(shù)組中移除事件 } } /** * Dispatches an action. It is the only way to trigger a state change. * * dispatch action是唯一觸發(fā)state改變的途徑 * * The `reducer` function, used to create the store, will be called with the * current state tree and the given `action`. Its return value will * be considered the **next** state of the tree, and the change listeners * will be notified. * * `reducer`函數(shù),被用來(lái)創(chuàng)建store,有當(dāng)前的state樹(shù)和action就會(huì)被調(diào)用(state和action是reducer函數(shù)的參數(shù)) * 它的返回值會(huì)被當(dāng)做下一個(gè)state樹(shù).監(jiān)聽(tīng)事件會(huì)注意到state樹(shù)的改變 * * The base implementation only supports plain object actions. If you want to * dispatch a Promise, an Observable, a thunk, or something else, you need to * wrap your store creating function into the corresponding middleware. For * example, see the documentation for the `redux-thunk` package. Even the * middleware will eventually dispatch plain object actions using this method. * * 最基本的用法是僅支持 為純對(duì)象的 action,如果你想要dispatch一個(gè)promise,一個(gè)Observable, * thunk,或是其他東西,你需要封裝store創(chuàng)建一個(gè)進(jìn)入到相應(yīng)中間件的函數(shù). 比如,看一個(gè)`redux-thunk` * 的文檔,即使是中間件最終也會(huì)用這個(gè)方法dispatch 純對(duì)象的action * * @param {Object} action A plain object representing “what changed”. It is * a good idea to keep actions serializable so you can record and replay user * sessions, or use the time travelling `redux-devtools`. An action must have * a `type` property which may not be `undefined`. It is a good idea to use * string constants for action types. * * action是一個(gè)純對(duì)象,代表"什么被改變了". 保持action的連續(xù)性是個(gè)好主意,這樣你就可以記錄和 * 重現(xiàn)user session,或者使用時(shí)空穿梭`redux-devtools`. * action必須包含一個(gè)`type`屬性,即使是`undefined`. 通常使用字符串常量表示 * * @returns {Object} For convenience, the same action object you dispatched. * * 為了方便,返回你dispatch的action * * Note that, if you use a custom middleware, it may wrap `dispatch()` to * return something else (for example, a Promise you can await). * 注意 如果你想使用特定的中間件,可封裝`dispatch`返回其他東西(比如, 一個(gè)異步調(diào)用的promise) * */ function dispatch(action) { if (!isPlainObject(action)) { throw new Error( "Actions must be plain objects. " + "Use custom middleware for async actions." )//actions必須為純對(duì)象,使用特定中間件異步調(diào)用actions } if (typeof action.type === "undefined") { throw new Error( "Actions may not have an undefined "type" property. " + "Have you misspelled a constant?" )//actions可能有一個(gè)未定義的type屬性,你可能拼錯(cuò)了這個(gè)常量 } if (isDispatching) { throw new Error("Reducers may not dispatch actions.")//reducer沒(méi)有dispatch action } try { isDispatching = true //dispatch的目的就是改變currentState currentState = currentReducer(currentState, action) //currentReducer = reducer } finally { isDispatching = false } const listeners = currentListeners = nextListeners //訂閱函數(shù)的事件 for (let i = 0; i < listeners.length; i++) { const listener = listeners[i] listener() } return action } /** * Replaces the reducer currently used by the store to calculate the state. * * 替換 store 當(dāng)前用來(lái)計(jì)算 state 的 reducer。 * * You might need this if your app implements code splitting and you want to * load some of the reducers dynamically. You might also need this if you * implement a hot reloading mechanism for Redux. * * 這是一個(gè)高級(jí) API。只有在你需要實(shí)現(xiàn)代碼分隔,而且需要立即加載一些 reducer 的時(shí)候才可能會(huì)用到它。 *在實(shí)現(xiàn) Redux 熱加載機(jī)制的時(shí)候也可能會(huì)用到 * * @param {Function} nextReducer The reducer for the store to use instead. * store所替換的reducer * @returns {void} */ function replaceReducer(nextReducer) { if (typeof nextReducer !== "function") { throw new Error("Expected the nextReducer to be a function.") } currentReducer = nextReducer dispatch({ type: ActionTypes.INIT }) } /** * Interoperability point for observable/reactive libraries. * @returns {observable} A minimal observable of state changes. * For more information, see the observable proposal: * https://github.com/tc39/proposal-observable * * observable/reactive庫(kù)的互用性 * observable是一個(gè)mini的 可觀察state的改變 * 在下面這個(gè)網(wǎng)址查看更多observable的信息 */ function observable() { const outerSubscribe = subscribe return { /** * The minimal observable subscription method. * @param {Object} observer Any object that can be used as an observer. * The observer object should have a `next` method. * @returns {subscription} An object with an `unsubscribe` method that can * be used to unsubscribe the observable from the store, and prevent further * emission of values from the observable. * * mini的可觀察訂閱的方法 * observer是 任何對(duì)象都可以用作觀察者,這個(gè)觀察者應(yīng)該有一個(gè)`next`方法 * subscription 一個(gè)有`unsubscribe`方法的對(duì)象.可以用做退訂observable,防止進(jìn)一步發(fā)出value值 * (我也不知道什么意思,外國(guó)人說(shuō)話(huà)比較隨意) */ subscribe(observer) { if (typeof observer !== "object") { throw new TypeError("Expected the observer to be an object.") } function observeState() { if (observer.next) { observer.next(getState()) } } observeState() const unsubscribe = outerSubscribe(observeState) return { unsubscribe } }, [$$observable]() { return this } } } // When a store is created, an "INIT" action is dispatched so that every // reducer returns their initial state. This effectively populates // the initial state tree. /** * 當(dāng)創(chuàng)建一個(gè)store的時(shí)候,一個(gè)初始的action就被dispatch了,所以每個(gè)reducer都會(huì)返回初始的state * 這個(gè)可以很高效的得到state樹(shù) */ dispatch({ type: ActionTypes.INIT }) return { dispatch, subscribe, getState, replaceReducer, [$$observable]: observable } }
源碼解析請(qǐng)參考 https://segmentfault.com/a/11...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/102363.html
摘要:是這個(gè)函數(shù)名翻譯為獲取未定義的錯(cuò)誤信息對(duì)于返回一定要很明確的返回之前的這樣就可以忽略一個(gè)如果你想這個(gè)沒(méi)有返回值你可以返回而不是獲取與預(yù)期不符的的結(jié)構(gòu)警告信息聲明結(jié)構(gòu)初始化時(shí)返回如果傳給的是你一定要很明確地返回初始初始可能是如果你不想給這 import { ActionTypes } from ./createStore import isPlainObject from lodash/...
摘要:理解需要跟結(jié)合首先來(lái)看是怎樣創(chuàng)建的再來(lái)看的源碼的第三個(gè)參數(shù)就是此時(shí)會(huì)返回也就是在中間件里面去執(zhí)行了返回的是函數(shù)也就是函數(shù)然后又跑到里面作為第三個(gè)參數(shù)所以能把作為參數(shù)傳進(jìn)去一個(gè)小例子測(cè)試返回函數(shù)后是什么東西創(chuàng)建一個(gè)的方法使用中間件的增強(qiáng)器對(duì)于 理解applyMiddleware需要跟createStore結(jié)合.首先來(lái)看createStore是怎樣創(chuàng)建store的. showImg(htt...
摘要:函數(shù)組合,科里化的串聯(lián)結(jié)合示例源碼,實(shí)現(xiàn)也很優(yōu)雅,對(duì)于返回的,將等參數(shù)傳遞進(jìn)去,然后執(zhí)行,等待回調(diào)異步完成再。對(duì)于正常對(duì)象則進(jìn)行下一步。前言 作為前端狀態(tài)管理器,這個(gè)比較跨時(shí)代的工具庫(kù)redux有很多實(shí)現(xiàn)和思想值得我們思考。在深入源碼之前,我們可以相關(guān)注下一些常見(jiàn)問(wèn)題,這樣帶著問(wèn)題去看實(shí)現(xiàn),也能更加清晰的了解。 常見(jiàn)問(wèn)題 大概看了下主要有這么幾個(gè): redux三大原則 這個(gè)可以直接參考...
摘要:在英文中的意思是有效載荷。有一個(gè)動(dòng)作被發(fā)射了顧名思義,替換,這主要是方便開(kāi)發(fā)者調(diào)試用的。相同的輸入必須返回相同的輸出,而且不能對(duì)外產(chǎn)生副作用。怎么辦呢開(kāi)發(fā)者得手動(dòng)維護(hù)一個(gè)訂閱器,才能監(jiān)聽(tīng)到狀態(tài)變化,從而觸發(fā)頁(yè)面重新渲染。 本文是『horseshoe·Redux專(zhuān)題』系列文章之一,后續(xù)會(huì)有更多專(zhuān)題推出來(lái)我的 GitHub repo 閱讀完整的專(zhuān)題文章來(lái)我的 個(gè)人博客 獲得無(wú)與倫比的閱讀體...
摘要:接下來(lái)我們來(lái)看看源碼中的模塊是怎么應(yīng)用中間件的。如何實(shí)現(xiàn)中間件操作的。新的會(huì)從第一個(gè)中間件開(kāi)始觸發(fā),這樣,在我們調(diào)用的時(shí)候,就會(huì)將中間件走一遍了。函數(shù)如果存在多個(gè)中間件,直接使用方法將各個(gè)中間件嵌套起來(lái)。 從redux-thunk引出思考 在使用redux-thunk進(jìn)行異步action書(shū)寫(xiě)的時(shí)候,我經(jīng)常好奇redux到底如何運(yùn)作,讓asyncAction成為可能 為了探究,我們必須看...
閱讀 2470·2021-09-28 09:36
閱讀 3612·2021-09-22 15:41
閱讀 4418·2021-09-04 16:45
閱讀 2012·2019-08-30 15:55
閱讀 2853·2019-08-30 13:49
閱讀 833·2019-08-29 16:34
閱讀 2379·2019-08-29 12:57
閱讀 1691·2019-08-26 18:42