redux源码

来源:互联网 发布:unity3d飞机模型 编辑:程序博客网 时间:2024/05/16 05:22

redux是什么?github上的介绍是Predictable state container for JavaScript apps,js应用的可预测的状态容器。

1、使用createStore创建store,store用于管理state

 createStore(reducer, preloadedState, enhancer)// 传入preloadedState对象作为redux的默认state,当使用combineReducers()方法合并多个reducer时,传入的preloadedState对象key值必须与合并reducer时传入的key一致/** * 创建唯一的redex 容器,用于存储state树,只能通过dispatch()改变数据, * 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`. * * @param {Function} reducer A function that returns the next state tree, given * the current state tree and the action to handle. * * @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 {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()`. * * @returns {Store} A Redux store that lets you read the state, dispatch actions * and subscribe to changes. */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.')    }    return enhancer(createStore)(reducer, preloadedState)  }  if (typeof reducer !== 'function') {    throw new Error('Expected the reducer to be a function.')  }  let currentReducer = reducer  // 用于存储数据的state  let currentState = preloadedState  let currentListeners = []  let nextListeners = currentListeners  let isDispatching = false  function ensureCanMutateNextListeners() {    if (nextListeners === currentListeners) {      nextListeners = currentListeners.slice()    }  }  /**   * Reads the state tree managed by the store.   * 读取当前state树   * @returns {any} The current state tree of your application.   */  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.   *   * You may call `dispatch()` from a change listener, with the following   * caveats:   *   * 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.   *   * 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.   *   * @param {Function} listener A callback to be invoked on every dispatch.   * @returns {Function} A function to remove this change listener.   */  function subscribe(listener) {    if (typeof listener !== 'function') {      throw new Error('Expected listener to be a function.')    }    let isSubscribed = true    ensureCanMutateNextListeners()    nextListeners.push(listener)    return function unsubscribe() {      if (!isSubscribed) {        return      }      isSubscribed = false      ensureCanMutateNextListeners()      const index = nextListeners.indexOf(listener)      nextListeners.splice(index, 1)    }  }  /**   * Dispatches an action. It is the only way to trigger a state change.   *   * 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.   *   * 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.   *   * @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.   *   * @returns {Object} For convenience, the same action object you dispatched.   *   * Note that, if you use a custom middleware, it may wrap `dispatch()` to   * return something else (for example, a Promise you can await).   */  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 = true      currentState = 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  }  /**   * Replaces the reducer currently used by the store to calculate the state.   *   * 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.   *   * @param {Function} nextReducer The reducer for the store to use instead.   * @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   */  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.       */      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.  dispatch({ type: ActionTypes.INIT })  return {    dispatch,    subscribe,    getState,    replaceReducer,    [$$observable]: observable  }}

2、在创建reducer时,传入初始化initialState

const initialState = {}export default function(state = initialState, action) {    return state}
0 0
原创粉丝点击