国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Redux系列源碼解讀

Scliang / 1011人閱讀

摘要:源碼解讀的方法就是給我們提供了靈活的創(chuàng)建符合標準的的方法。用于分解樹,每一個對應的一個對應的子。這樣在將傳遞給時利于分解。源碼實現(xiàn)了這種將函數(shù)數(shù)組,通過的方法,實現(xiàn)層層嵌套的執(zhí)行,達到中間件的實現(xiàn)。

Redux 源碼解讀 1.redux-action createAction

redux-action的createAction方法就是給我們提供了靈活的創(chuàng)建符合FSA標準的action的方法。

exports.default = createAction;
 
/**
  返回創(chuàng)建action的函數(shù)
*/
function createAction(type, payloadCreator, metaCreator) {
  var finalPayloadCreator = typeof payloadCreator === "function" ? payloadCreator : _identity2.default;
  /**
    返回的函數(shù)
  */
  var actionHandler = function actionHandler() {
    var hasError = (arguments.length <= 0 ? undefined : arguments[0]) instanceof Error;
  /**
    返回的action
  */
    var action = {
      type: type
    };
    //根據(jù)傳入的參數(shù),執(zhí)行payloadCreator獲取payload
    var payload = hasError ? arguments.length <= 0 ? undefined : arguments[0] : finalPayloadCreator.apply(undefined, arguments);
    if (!(payload === null || payload === undefined)) {
      action.payload = payload;
    }
 
    if (hasError) {
      // Handle FSA errors where the payload is an Error object. Set error.
      action.error = true;
    }
  //根據(jù)傳入的參數(shù),執(zhí)行metaCreator獲取payload
    if (typeof metaCreator === "function") {
      action.meta = metaCreator.apply(undefined, arguments);
    }
    //可以看到  payloadCreator和metaCreator的參數(shù)都是用的傳給actionHandler的參數(shù)
 
    return action;
  };
 
  actionHandler.toString = function () {
    return type.toString();
  };
 
  return actionHandler;
}
2.redux combineReducer

redux的combineReducer方法 用于將多個reducer,合并成一個大的reducer函數(shù),傳給store。

用于分解state樹,每一個reducer對應state的一個key對應的子state。比如poi的reducer對應的就是state[poi]。這樣在將state傳遞給props時利于分解。

reducer以對象的形式傳入,finalReducers 存放最終的reducer,finalReducerKeys存放reducer的key
最終返回  combination函數(shù) reducer類型的函數(shù),接受state和action 返回state
 
state的形式是一個大對象下面每一個reducer對應一個子state。
 
觸發(fā)一個action,會遍歷所有的reducer,
將該reducer的舊state和action傳入,然后根據(jù)返回的新的state對象是否改變,來決定
最終的返回的state是否改變。
這里需要注意:由于state都是引用類型,這里比較是值比較
hasChanged = hasChanged || nextStateForKey !== previousStateForKey
 
所以如果我們想要改變全局的state,需要在reducer中返回新的對象,而不是原來的state對象,
如果返回原來的對象,即使對象里的值改變了,也不會引起全局state的改變。
 */
export default function combineReducers(reducers) {
  var reducerKeys = Object.keys(reducers)
  var finalReducers = {}
  for (var i = 0; i < reducerKeys.length; i++) {
    var key = reducerKeys[i]
 
    if (process.env.NODE_ENV !== "production") {
      if (typeof reducers[key] === "undefined") {
        warning(`No reducer provided for key "${key}"`)
      }
    }
 
    if (typeof reducers[key] === "function") {
      finalReducers[key] = reducers[key]
    }
  }
  var finalReducerKeys = Object.keys(finalReducers)
 
  return function combination(state = {}, action) {
    /**
     校驗語法錯誤,reducer返回的state不能是undefined
    */
    if (sanityError) {
      throw sanityError
    }
 
    var hasChanged = false
    var nextState = {}
    for (var i = 0; i < finalReducerKeys.length; i++) {
      var key = finalReducerKeys[i]
      var reducer = finalReducers[key]
      var previousStateForKey = state[key]
      var nextStateForKey = reducer(previousStateForKey, action)
      if (typeof nextStateForKey === "undefined") {
        var errorMessage = getUndefinedStateErrorMessage(key, action)
        throw new Error(errorMessage)
      }
      nextState[key] = nextStateForKey
      /**
        所以如果我們想要改變全局的state,需要在reducer中返回新的對象,而不是原來的state對象,
        如果返回原來的對象,即使對象里的值改變了,也不會引起全局state的改變。
      */
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey
    }
    return hasChanged ? nextState : state
  }
}
3 redux applyMiddleware

應用中間件的目的是包裝dispatch,在action傳遞給dispatch執(zhí)行之前,需要經(jīng)過中間件的層層處理,進行一些業(yè)務上的處理,決定action的走向。

源碼實現(xiàn)了這種將函數(shù)數(shù)組,通過reducerRight的方法,實現(xiàn)層層嵌套的執(zhí)行,達到中間件的實現(xiàn)。

/**
  顯示執(zhí)行中間件,得到中間件的返回函數(shù)數(shù)組chain,然后利用compose方法,生成嵌套的執(zhí)行chain
  方法的包裝dispatch函數(shù),
  中間件的形式是
  (getState, dispatch)=> next => action => {
     next(action);
  }
 */
export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    var store = createStore(reducer, preloadedState, enhancer)
    var dispatch = store.dispatch
    var chain = []
 
    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)
    /**
    store.dispatch 就是第一個next  是last ware的next
    (...args) => {
      return ware0(ware1(ware2(last(...args))))
    }
    dispatch = ware0(ware1(ware2(last(...args))))
    所以中間件中next傳入后返回的函數(shù)就是我們需要的函數(shù)形式,
    例如dispatch 需要的函數(shù)形式是 傳一個action
    */
    return {
      ...store,
      dispatch
    }
  }
}
 
/**
reduceRight是數(shù)組的從右至左執(zhí)行,
初始的參數(shù)是最后一個函數(shù)接受dispatch,
的到的一個action=>{
    dispatch(action);
}
形式的函數(shù),作為參數(shù)composed
f的形式是
next=>action=>{
}
最終形成的就是
(...args) => {
    return funcs0(funcs1(funcs2(last(...args))))
}
*/
export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }
 
  if (funcs.length === 1) {
    return funcs[0]
  }
 
  const last = funcs[funcs.length - 1]
  const rest = funcs.slice(0, -1)
  return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args))
}

中間件執(zhí)行過程模擬

中間件原理
*/
function func1 (next) {
    console.log("func1 return");
    return function (action) {
        console.log("func1start");
        next(action);
        console.log("func1end");
    }
     
}
function func2 (next) {
    console.log("func2 return");
    return function (action) {
        console.log("func2start");
        next(action);
        console.log("func2end");
    }
}
function func3 (next) {
    console.log("func3 return");
    return function (action) {
        console.log("func3start");
        next(action);
        console.log("func3end");
    }
}
 
function dispatch(action) {
    console.log(action);
}
 
function afterCompose (args) {
    return func1(func2(func3(args)));
}
 
var newdispatch = afterCompose(dispatch);
newdispatch("action");
/**
    執(zhí)行順序
    func3 return
    func2 return
    func1 return
    func1start
    func2start
    func3start
    action
    func3end
    func2end
    func1end
*/
4 redux createStore

應用場景參見中間件的應用代碼與applyMiddleware源碼,是redux提供創(chuàng)建store的方法。

import isPlainObject from "lodash/isPlainObject"
import $$observable from "symbol-observable"
 
export var ActionTypes = {
  INIT: "@@redux/INIT"
}
 
export default function createStore(reducer, preloadedState, enhancer) {
  var currentReducer = reducer
  var currentState = preloadedState
  var currentListeners = []
  var nextListeners = currentListeners
  var isDispatching = false
 
  function ensureCanMutateNextListeners() {
    if (nextListeners === currentListeners) {
      nextListeners = currentListeners.slice()
    }
  }
 
  function getState() {
    return currentState
  }
 
   /**
    訂閱監(jiān)聽
   */
  function subscribe(listener) {
    if (typeof listener !== "function") {
      throw new Error("Expected listener to be a function.")
    }
 
    var isSubscribed = true
 
    ensureCanMutateNextListeners()
    nextListeners.push(listener)
 
    return function unsubscribe() {
      if (!isSubscribed) {
        return
      }
 
      isSubscribed = false
 
      ensureCanMutateNextListeners()
      var index = nextListeners.indexOf(listener)
      nextListeners.splice(index, 1)
    }
  }
 
   /**
    執(zhí)行reducer,獲取state,執(zhí)行l(wèi)istener
   */
  function dispatch(action) {
    try {
      isDispatching = true
      currentState = currentReducer(currentState, action)
    } finally {
      isDispatching = false
    }
 
    var listeners = currentListeners = nextListeners
    for (var i = 0; i < listeners.length; i++) {
      listeners[i]()
    }
    return action
  }
 
   /**
    替換reducer
   */
  function replaceReducer(nextReducer) {
    if (typeof nextReducer !== "function") {
      throw new Error("Expected the nextReducer to be a function.")
    }
    currentReducer = nextReducer
    dispatch({ type: ActionTypes.INIT })
  }
 
 
  /**
    store創(chuàng)建的時候,獲取初始的sate樹
  */
  dispatch({ type: ActionTypes.INIT })
 
  return {
    dispatch,
    subscribe,
    getState,
    replaceReducer
  }
}
5. react-redux Provider

redux和react的結合,Provider作為根組件,將store的state放在context中供子組件使用。

import { Component, PropTypes, Children } from "react"
import storeShape from "../utils/storeShape"
import warning from "../utils/warning"
 
 
export default class Provider extends Component {
  //把 store 放在context里面,給子元素用
  getChildContext() {
    return { store: this.store }
  }
 
  constructor(props, context) {
    super(props, context)
    this.store = props.store
  }
 
  render() {
    const { children } = this.props
    //渲染唯一的子元素
    return Children.only(children)
  }
}
 
Provider.propTypes = {
  store: storeShape.isRequired,
  children: PropTypes.element.isRequired
}
Provider.childContextTypes = {
  store: storeShape.isRequired
}
6. react-redux connect

connect方法,將React的組件進行包裝,包裝的目的如下:

能夠將store中指定的state,傳遞給組件當props

能夠監(jiān)聽store中state的變化

能夠將action傳遞給view

const defaultMapStateToProps = state => ({}) // eslint-disable-line no-unused-vars
const defaultMapDispatchToProps = dispatch => ({ dispatch })
const defaultMergeProps = (stateProps, dispatchProps, parentProps) => ({
  ...parentProps,
  ...stateProps,
  ...dispatchProps
})
 
 
export default function connect(mapStateToProps, mapDispatchToProps, mergeProps, options = {}) {
 
  //返回包裝組件的函數(shù)
  return function wrapWithConnect(WrappedComponent) {
 
    class Connect extends Component {
      shouldComponentUpdate() {
        return !pure || this.haveOwnPropsChanged || this.hasStoreStateChanged
      }
 
      constructor(props, context) {
        super(props, context)
        this.version = version
        this.store = props.store || context.store
 
       
        const storeState = this.store.getState()
        this.state = { storeState }
        this.clearCache()
      }
 
      isSubscribed() {
        return typeof this.unsubscribe === "function"
      }
 
      trySubscribe() {
        if (shouldSubscribe && !this.unsubscribe) {
          //訂閱store的state變化
          this.unsubscribe = this.store.subscribe(this.handleChange.bind(this))
          this.handleChange()
        }
      }
 
      tryUnsubscribe() {
        if (this.unsubscribe) {
          this.unsubscribe()
          this.unsubscribe = null
        }
      }
 
      componentDidMount() {
        //訂閱store的state變化
        this.trySubscribe()
      }
 
      componentWillReceiveProps(nextProps) {
        if (!pure || !shallowEqual(nextProps, this.props)) {
          this.haveOwnPropsChanged = true
        }
      }
 
      componentWillUnmount() {
        this.tryUnsubscribe()
        this.clearCache()
      }
 
      //訂閱變化
      handleChange() {
        if (!this.unsubscribe) {
          return
        }
 
        const storeState = this.store.getState()
        const prevStoreState = this.state.storeState
        if (pure && prevStoreState === storeState) {
          return
        }
 
        if (pure && !this.doStatePropsDependOnOwnProps) {
          const haveStatePropsChanged = tryCatch(this.updateStatePropsIfNeeded, this)
          if (!haveStatePropsChanged) {
            return
          }
          if (haveStatePropsChanged === errorObject) {
            this.statePropsPrecalculationError = errorObject.value
          }
          this.haveStatePropsBeenPrecalculated = true
        }
 
        this.hasStoreStateChanged = true
        //如果有變化 setState,觸發(fā)render
        this.setState({ storeState })
      }
 
      render() {
        const {
          haveOwnPropsChanged,
          hasStoreStateChanged,
          haveStatePropsBeenPrecalculated,
          statePropsPrecalculationError,
          renderedElement
        } = this
 
        
        //最終渲染組件,將合并屬性傳遞給WrappedComponent
        if (withRef) {
          this.renderedElement = createElement(WrappedComponent, {
            ...this.mergedProps,
            ref: "wrappedInstance"
          })
        } else {
          this.renderedElement = createElement(WrappedComponent,
            this.mergedProps
          )
        }
 
        return this.renderedElement
      }
    }
 
    Connect.displayName = connectDisplayName
    Connect.WrappedComponent = WrappedComponent
    Connect.contextTypes = {
      store: storeShape
    }
    Connect.propTypes = {
      store: storeShape
    }
 
    //把WrappedComponent的非靜態(tài)react屬性 復制到Connect,最終返回Connect
    return hoistStatics(Connect, WrappedComponent)
  }
}
7. redux bindActionCreators

使用實例參見 react-redux connect 的使用實例

function bindActionCreator(actionCreator, dispatch) {
  return (...args) => dispatch(actionCreator(...args))
}
 
 
  將actionCreators綁定上dispatch,key還是actionCreators的key,但是多做了一層dispatch
 */
export default function bindActionCreators(actionCreators, dispatch) {
  if (typeof actionCreators === "function") {
    return bindActionCreator(actionCreators, dispatch)
  }
 
  if (typeof actionCreators !== "object" || actionCreators === null) {
    throw new Error(
      `bindActionCreators expected an object or a function, instead received ${actionCreators === null ? "null" : typeof actionCreators}. ` +
      `Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?`
    )
  }
 
  var keys = Object.keys(actionCreators)
  var boundActionCreators = {}
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i]
    var actionCreator = actionCreators[key]
    if (typeof actionCreator === "function") {
      boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
    }
  }
  return boundActionCreators
}

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/80813.html

相關文章

  • dva系列源碼解讀

    摘要:介紹概述本次對源碼的解讀除了傳統(tǒng)的從入手外還將引入帶入問題讀源碼的理念,因為只有這樣當讀完源碼之后才會有切身的收獲。 介紹 概述 本次對 dva 源碼的解讀除了傳統(tǒng)的從 api 入手外還將引入帶入問題讀源碼的理念,因為只有這樣當讀完源碼之后才會有切身的收獲。另外除了 dva 的源碼外還會解讀一些常用的 dva 插件的源碼。 電子書 https://dva-source-docs.net...

    focusj 評論0 收藏0
  • redux源碼解讀--applyMiddleware源碼解析

    摘要:的中間件主要是通過模塊實現(xiàn)的。返回的也是一個對象這個其實就是,各個中間件的最底層第三層的哪個函數(shù)組成的圓環(huán)函數(shù)構成的這就是對源碼的一個整體解讀,水平有限,歡迎拍磚。后續(xù)的源碼解讀和測試例子可以關注源碼解讀倉庫 applyMiddleware源碼解析 中間件機制在redux中是強大且便捷的,利用redux的中間件我們能夠實現(xiàn)日志記錄,異步調用等多種十分實用的功能。redux的中間件主要是...

    Atom 評論0 收藏0
  • 精讀《源碼學習》

    摘要:精讀原文介紹了學習源碼的兩個技巧,并利用實例說明了源碼學習過程中可以學到許多周邊知識,都讓我們受益匪淺。討論地址是精讀源碼學習如果你想?yún)⑴c討論,請點擊這里,每周都有新的主題,周末或周一發(fā)布。 1. 引言 javascript-knowledge-reading-source-code 這篇文章介紹了閱讀源碼的重要性,精讀系列也已有八期源碼系列文章,分別是: 精讀《Immer.js》源...

    aboutU 評論0 收藏0
  • 不一樣的redux源碼解讀

    摘要:這里還有一個疑問點就是的嵌套,最開始也我不明白,看了源碼才知道,這里返回的也是接受也就是一個所以可以正常嵌套。以作為參數(shù),調用上一步返回的函數(shù)以為參數(shù)進行調用。 1、本文不涉及redux的使用方法,因此可能更適合使用過 redux 的同學閱讀2、當前redux版本為4.0.13、更多系列文章請看 Redux作為大型React應用狀態(tài)管理最常用的工具。雖然在平時的工作中很多次的用到了它...

    Salamander 評論0 收藏0
  • redux源碼解讀--compose源碼解析

    摘要:源碼解析模塊的代碼十分簡練,但是實現(xiàn)的作用卻是十分強大。只傳遞一個參數(shù)的時候,就直接把這個函數(shù)返回返回組合函數(shù)這就是對源碼的一個整體解讀,水平有限,歡迎拍磚。后續(xù)的源碼解讀和測試例子可以關注源碼解讀倉庫 compose源碼解析 compose模塊的代碼十分簡練,但是實現(xiàn)的作用卻是十分強大。redux為何稱為redux?有人說就是reduce和flux的結合體,而reduce正是comp...

    lk20150415 評論0 收藏0

發(fā)表評論

0條評論

Scliang

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<