摘要:為了能夠更好的使用這個工具,今天就對它進行一下源碼剖析。它內部的關鍵代碼是在不指定的時候等于,這就意味著的源碼剖析到此結束,謝謝觀看當然如果指定了剖析就還得繼續。好了,源碼剖析到此結束,謝謝觀看
React-Redux是用在連接React和Redux上的。如果你想同時用這兩個框架,那么React-Redux基本就是必須的了。為了能夠更好的使用這個工具,今天就對它進行一下源碼剖析。
Provider一個React組件,一般你的rootApp要放倒這個組件內部渲染。它很簡單,最關鍵的作用就是在context中放入Redux的store,方便子組件獲取。關鍵代碼:
getChildContext() { return { store: this.store } } Provider.childContextTypes = { store: storeShape.isRequired }
這樣connect的組件就可以獲取store,使用store的方法。
connect首選connect是個可以執行兩次的柯里化函數,第一次傳入的參數相當于一系列的定制化東西,第二次傳入的是你要連接的React組件,然后返回一個新的React組件。
第一次執行時傳入的參數是mapStateToProps, mapDispatchToProps, mergeProps, options這四個。首先會對這幾個參數進行處理,代碼如下:
//決定組件會不會因state改變而更新 const shouldSubscribe = Boolean(mapStateToProps) //如果不傳遞這個參數使用默認state => ({}) const mapState = mapStateToProps || defaultMapStateToProps //mapDispatchToProps的處理,最后的情況實際是使用bindActionCreators處理 let mapDispatch if (typeof mapDispatchToProps === "function") { mapDispatch = mapDispatchToProps } else if (!mapDispatchToProps) { mapDispatch = defaultMapDispatchToProps } else { mapDispatch = wrapActionCreators(mapDispatchToProps) } //不傳遞就使用默認值 const finalMergeProps = mergeProps || defaultMergeProps const { pure = true, withRef = false } = options
第二次執行函數接收的參數是個React組件:WrappedComponent,之后返回一個新的React組件Connect。
return hoistStatics(Connect, WrappedComponent)
把WrappedComponent的非React屬性拷貝到Connect上。下面詳細說下Connect。
Connect一個React組件
Connect.contextTypes = { store: storeShape }
所以它可以從context中獲取Provider放的store。
constructor在constructor中:
//獲取store this.store = props.store || context.store const storeState = this.store.getState() //把store的state作為組件的state,后面通過更新state更新組件 this.state = { storeState } //清除組件的狀態,內部是一系列的標示還原 this.clearCache()render
然后是render方法,在掛載的時候,會經過一系列的判斷和計算,比如使用mapState計算nextStateProps,并和this.stateProps對比是否發生改變,如果發生改變:
nextDispatchProps = mapState(store.getState(), [props]) this.stateProps = nextDispatchProps
使用mapDispatch計算nextDispatchProps,并和this.dispatchProps對比是否發生改變,如果發生改變:
nextMergedProps = mapDispatch(dispatch, [props]) this.dispatchProps = nextMergedProps
如果上面的兩個對比有一個發生改變,就會繼續使用finalMergeProps來計算最終的數據合并結果nextMergedProps,并和this.mergedProps對比是否發生改變,如果發生改變:
nextMergedProps = finalMergeProps(this.stateProps, this.dispatchProps, this.props) this.mergedProps = nextMergedProps
如果上面的對比確定發生改變
if (withRef) { this.renderedElement = createElement(WrappedComponent, { ...this.mergedProps, ref: "wrappedInstance" }) } else { this.renderedElement = createElement(WrappedComponent, this.mergedProps ) } return this.renderedElement
如果withRef等于true就會增加ref屬性,然后可以通過getWrappedInstance方法獲取DOM。如果前面說的這些對比的結果都是false,就會直接返回this.renderedElement,組件不進行任何更新。當然組件掛載的時候前面的對比都會返回true。
componentDidMount它內部的關鍵代碼是:
if (shouldSubscribe && !this.unsubscribe) { this.unsubscribe = this.store.subscribe(this.handleChange.bind(this)) this.handleChange() }
在不指定mapStateToProps的時候shouldSubscribe等于false,這就意味著React-Redux的源碼剖析到此結束,謝謝觀看!當然如果指定了mapStateToProps剖析就還得繼續。看到代碼沒有,竟然使用subscribe,意味著只要執行dispatch,handleChange就會執行。至此組件已經掛載完畢,后面的代碼執行需要有外界因素了,比如父組件傳遞新的props、執行dispatch。
componentWillReceiveProps組件還實現了componentWillReceiveProps這個React生命周期中的方法:
componentWillReceiveProps(nextProps) { if (!pure || !shallowEqual(nextProps, this.props)) { this.haveOwnPropsChanged = true } }
看到pure的重要性了吧,如果pure被設置為false就意味著不管屬性是否淺相等this.haveOwnPropsChanged總是會被設置為true,而這會導致后面一系列的為了更新而進行的計算,所以pure為true是可以給你的性能帶來幫助的,不過它默認就是true。這里設置this.haveOwnPropsChanged等于true是給通過直接通過父組件傳遞props更新組件帶來可能,當然需要配合mapStateToProps, mapDispatchToProps, mergeProps這三個函數,如果它們都沒有利用ownProps,最終組件還是不能通過這種方式更新。
handleChange下面假定觸發了一次dispatch,這個時候handleChange就會執行,如果state沒有發生改變,并且pure為true,就什么都不做直接返回,pure又在性能上立功了。如果state發生了改變會再做一些計算對比,比如計算this.stateProps。最后是在要更新的時候會:
this.hasStoreStateChanged = true this.setState({ storeState })
調用setState來觸發組件更新。這里其實意味著只要store的state發生改變,所有的mapStateToProps、 mapDispatchToProps、mergeProps都會執行。
shouldComponentUpdate這個時候會調用它內部實現的shouldComponentUpdate,用來提高性能。
shouldComponentUpdate() { return !pure || this.haveOwnPropsChanged || this.hasStoreStateChanged }
但是怎么感覺這個并沒有什么用呢?可能是我理解不深,因為無論是父組件更新props還是state改變這里總是返回true,而不管改變的是不是這個組件關心的數據。沒辦法又進入了render方法。
好了,源碼剖析到此結束,謝謝觀看!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/80034.html
摘要:到月底了,小明的爸爸的單位發了工資總計塊大洋,拿到工資之后第一件的事情就是上交,毫無疑問的,除非小明爸爸不要命了。當小明的爸爸收到這個通知之后,心的一塊大石頭也就放下來了。下面我們正式開始我們的源碼閱讀之旅。 前言 用過react的小伙伴對redux其實并不陌生,基本大多數的React應用用到它。一般大家用redux的時候基本都不會單獨去使用它,而是配合react-redux一起去使用...
摘要:接下來筆者就從源碼中探尋是如何實現的。其實很簡單,可以簡單理解為一個約束了特定規則并且包括了一些特殊概念的的發布訂閱器。新舊中存在的任何都將收到先前的狀態。這有效地使用來自舊狀態樹的任何相關數據填充新狀態樹。 Redux是當今比較流行的狀態管理庫,它不依賴于任何的框架,并且配合著react-redux的使用,Redux在很多公司的React項目中起到了舉足輕重的作用。接下來筆者就從源碼...
摘要:調用鏈中最后一個會接受真實的的方法作為參數,并借此結束調用鏈。總結我們常用的一般是除了和之外的方法,那個理解明白了,對于以后出現的問題會有很大幫助,本文只是針對最基礎的進行解析,之后有機會繼續解析對他的封裝 前言 雖然一直使用redux+react-redux,但是并沒有真正去講redux最基礎的部分理解透徹,我覺得理解明白redux會對react-redux有一個透徹的理解。 其實,...
摘要:異步實戰狀態管理與組件通信組件通信其他狀態管理當需要改變應用的狀態或有需要更新時,你需要觸發一個把和載荷封裝成一個。的行為是同步的。所有的狀態變化必須通過通道。前端路由實現與源碼分析設計思想應用是一個狀態機,視圖與狀態是一一對應的。 React實戰與原理筆記 概念與工具集 jsx語法糖;cli;state管理;jest單元測試; webpack-bundle-analyzer Sto...
閱讀 1432·2021-11-22 15:24
閱讀 2523·2021-10-11 11:06
閱讀 2334·2021-10-09 09:45
閱讀 2532·2021-09-09 09:33
閱讀 639·2019-08-30 15:53
閱讀 1444·2019-08-30 12:48
閱讀 678·2019-08-29 13:47
閱讀 506·2019-08-26 18:27