磨刀不误砍柴工,咱先把react-redux里的工具函数分析一下:

源码点这里

 shallowEqual.js

 export default function shallowEqual(objA, objB) {
if (objA === objB) {
return true
} const keysA = Object.keys(objA)
const keysB = Object.keys(objB) if (keysA.length !== keysB.length) {
return false
} // Test for A's keys different from B.
const hasOwn = Object.prototype.hasOwnProperty
for (let i = 0; i < keysA.length; i++) {
if (!hasOwn.call(objB, keysA[i]) ||
objA[keysA[i]] !== objB[keysA[i]]) {
return false
}
} return true
}

这个几个api全都超级简单,我就不仔细讲解了,顾名思义,简单比较一下两个obj是否相等。

storeShape.js

 import { PropTypes } from 'react'

 export default PropTypes.shape({
subscribe: PropTypes.func.isRequired,
dispatch: PropTypes.func.isRequired,
getState: PropTypes.func.isRequired
})

顾名思义,强制性规定subscribe,dispacth,getState必须是func.

warning.js

 /**
* Prints a warning in the console if it exists.
*
* @param {String} message The warning message.
* @returns {void}
*/
export default function warning(message) {
/* eslint-disable no-console */
if (typeof console !== 'undefined' && typeof console.error === 'function') {
console.error(message)
}
/* eslint-enable no-console */
try {
// This error was thrown as a convenience so that if you enable
// "break on all exceptions" in your console,
// it would pause the execution at this line.
throw new Error(message)
/* eslint-disable no-empty */
} catch (e) {}
/* eslint-enable no-empty */
}

就是用console.error 打印一下错误。

wrapActionCreators.js

 import { bindActionCreators } from 'redux'

 export default function wrapActionCreators(actionCreators) {
return dispatch => bindActionCreators(actionCreators, dispatch)
}

上一篇讲过 bindActionCreators


它返回的这个对象直接是以 我们定义单个actionCreator为key的,actionCreator函数为value的包装,并在actionCreator里挂着了dispacth的函数。使用的时候,直接调用同名key函数,就直接分发action了,不需要

我们手动的 dispacth(actionCreator(内容)), 直接key(内容) 就行了。

------------------------------------------------------工具全部介绍完毕-----是不是so easy??!!!------------------------------

 现在主角登场:

Provider.js

 import { Component, PropTypes, Children } from 'react'
import storeShape from '../utils/storeShape'
import warning from '../utils/warning' let didWarnAboutReceivingStore = false
function warnAboutReceivingStore() {
if (didWarnAboutReceivingStore) {
return
}
didWarnAboutReceivingStore = true warning(
'<Provider> does not support changing `store` on the fly. ' +
'It is most likely that you see this error because you updated to ' +
'Redux 2.x and React Redux 2.x which no longer hot reload reducers ' +
'automatically. See https://github.com/reactjs/react-redux/releases/' +
'tag/v2.0.0 for the migration instructions.'
)
} export default class Provider extends Component { //关键部分,将this.store加到了context里,这里,子组件就可以通过context直接拿到store,不需要一级一级props传递下去。
getChildContext() {
return { store: this.store }
} constructor(props, context) {
super(props, context)
this.store = props.store
} render() {
return Children.only(this.props.children)
}
} if (process.env.NODE_ENV !== 'production') {
Provider.prototype.componentWillReceiveProps = function (nextProps) {
const { store } = this
const { store: nextStore } = nextProps if (store !== nextStore) {
warnAboutReceivingStore()
}
}
} Provider.propTypes = {
//要求我们的 store对象里面的3个必须是func
store: storeShape.isRequired, //要求我们形如这种格式的 <Provider store={store}> <App/> </Provider> ,<App>必须是react的element,其实它还要求了只能是放单element的,这也是render这个本身限定的!!可以看上面的Children.Only()
children: PropTypes.element.isRequired
}
// 这个是和getChildContext一样,必须加的。 //访问context 的属性是需要通过 contextTypes 指定可访问的 元素一样。getChildContext 指定的传递给子组件的属性需要先通过 childContextTypes 来指定,不然会产生错误。
Provider.childContextTypes = {
store: storeShape.isRequired
}

关于context的用法,我在github上写了一个小demo。大家可以clone下来跑一跑,在我的代码基础上可以添加一下状态函数,看看react的状态生命周期的流程。点这里

对于上面的代码总结一下,Provider这个React 组件就是为了将Store挂在到Context中,然后我们写的真正的app里就可以获得store了。

 connect.js


分析之前,我們心中要有這麽一個概念:

<Provider store={store}>
<App />
</Provider>, Provider的作用就是將 store挂在到 context上 提供App使用。 重點在這个 App上。 -----------------------------------------------------------------------------------------------------
这个App不是普通的element。它经过connect包装过,
connect(select)(App)

好了,可以开始分析了,我们将知道connect是啥,select是干嘛的?

------------------------------------------------------------------------------------------------

 import { Component, createElement } from 'react'
import storeShape from '../utils/storeShape'
import shallowEqual from '../utils/shallowEqual'
import wrapActionCreators from '../utils/wrapActionCreators'
import warning from '../utils/warning'
import isPlainObject from 'lodash/isPlainObject'
import hoistStatics from 'hoist-non-react-statics'
import invariant from 'invariant' //一直到return 我都认为是废话,函数名字都是顾名思义的。。直接忽略。。。。
const defaultMapStateToProps = state => ({}) // eslint-disable-line no-unused-vars
const defaultMapDispatchToProps = dispatch => ({ dispatch })
const defaultMergeProps = (stateProps, dispatchProps, parentProps) => ({
...parentProps,
...stateProps,
...dispatchProps
}) function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component'
} let errorObject = { value: null }
function tryCatch(fn, ctx) {
try {
return fn.apply(ctx)
} catch (e) {
errorObject.value = e
return errorObject
}
} // 重点开始了。。。。。。
// Helps track hot reloading.
let nextVersion = 0 export default function connect(mapStateToProps, mapDispatchToProps, mergeProps, options = {}) { //这里是否应该被订阅?嗯哼,回想一下store里的 subcribe,每次被dispacth 的时候就会执行!!!,这里估计就是给一个标志,
//如果传了mapStateToProps,必然是true,反之是false;
const shouldSubscribe = Boolean(mapStateToProps)

const mapState = mapStateToProps || defaultMapStateToProps 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
const checkMergedEquals = pure && finalMergeProps !== defaultMergeProps // Helps track hot reloading.
const version = nextVersion++ return function wrapWithConnect(WrappedComponent) { // 如果沒有為app添加disPlayName 或者 name 返回 "Conponent"
const connectDisplayName = `Connect(${getDisplayName(WrappedComponent)})` function checkStateShape(props, methodName) {
if (!isPlainObject(props)) {
warning(
`${methodName}() in ${connectDisplayName} must return a plain object. ` +
`Instead received ${props}.`
)
}
} function computeMergedProps(stateProps, dispatchProps, parentProps) {
const mergedProps = finalMergeProps(stateProps, dispatchProps, parentProps)
if (process.env.NODE_ENV !== 'production') {
checkStateShape(mergedProps, 'mergeProps')
}
return mergedProps
} 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 invariant(this.store,
`Could not find "store" in either the context or ` +
`props of "${connectDisplayName}". ` +
`Either wrap the root component in a <Provider>, ` +
`or explicitly pass "store" as a prop to "${connectDisplayName}".`
) const storeState = this.store.getState()
this.state = { storeState }
this.clearCache()
} computeStateProps(store, props) {
if (!this.finalMapStateToProps) {
return this.configureFinalMapState(store, props)
} const state = store.getState()
const stateProps = this.doStatePropsDependOnOwnProps ?
this.finalMapStateToProps(state, props) :
this.finalMapStateToProps(state) if (process.env.NODE_ENV !== 'production') {
checkStateShape(stateProps, 'mapStateToProps')
}
return stateProps
} configureFinalMapState(store, props) {
const mappedState = mapState(store.getState(), props)
const isFactory = typeof mappedState === 'function' this.finalMapStateToProps = isFactory ? mappedState : mapState
this.doStatePropsDependOnOwnProps = this.finalMapStateToProps.length !== 1 if (isFactory) {
return this.computeStateProps(store, props)
} if (process.env.NODE_ENV !== 'production') {
checkStateShape(mappedState, 'mapStateToProps')
}
return mappedState
} computeDispatchProps(store, props) {
if (!this.finalMapDispatchToProps) {
return this.configureFinalMapDispatch(store, props)
} const { dispatch } = store
const dispatchProps = this.doDispatchPropsDependOnOwnProps ?
this.finalMapDispatchToProps(dispatch, props) :
this.finalMapDispatchToProps(dispatch) if (process.env.NODE_ENV !== 'production') {
checkStateShape(dispatchProps, 'mapDispatchToProps')
}
return dispatchProps
} configureFinalMapDispatch(store, props) {
const mappedDispatch = mapDispatch(store.dispatch, props)
const isFactory = typeof mappedDispatch === 'function' this.finalMapDispatchToProps = isFactory ? mappedDispatch : mapDispatch
this.doDispatchPropsDependOnOwnProps = this.finalMapDispatchToProps.length !== 1 if (isFactory) {
return this.computeDispatchProps(store, props)
} if (process.env.NODE_ENV !== 'production') {
checkStateShape(mappedDispatch, 'mapDispatchToProps')
}
return mappedDispatch
} updateStatePropsIfNeeded() {
const nextStateProps = this.computeStateProps(this.store, this.props)
if (this.stateProps && shallowEqual(nextStateProps, this.stateProps)) {
return false
} this.stateProps = nextStateProps
return true
} updateDispatchPropsIfNeeded() {
const nextDispatchProps = this.computeDispatchProps(this.store, this.props)
if (this.dispatchProps && shallowEqual(nextDispatchProps, this.dispatchProps)) {
return false
} this.dispatchProps = nextDispatchProps
return true
} updateMergedPropsIfNeeded() {
const nextMergedProps = computeMergedProps(this.stateProps, this.dispatchProps, this.props)
if (this.mergedProps && checkMergedEquals && shallowEqual(nextMergedProps, this.mergedProps)) {
return false
} this.mergedProps = nextMergedProps
return true
} isSubscribed() {
return typeof this.unsubscribe === 'function'
} trySubscribe() {
if (shouldSubscribe && !this.unsubscribe) {
this.unsubscribe = this.store.subscribe(this.handleChange.bind(this))
this.handleChange()
}
} tryUnsubscribe() {
if (this.unsubscribe) {
this.unsubscribe()
this.unsubscribe = null
}
} componentDidMount() {
this.trySubscribe()
} componentWillReceiveProps(nextProps) {
if (!pure || !shallowEqual(nextProps, this.props)) {
this.haveOwnPropsChanged = true
}
} componentWillUnmount() {
this.tryUnsubscribe()
this.clearCache()
} clearCache() {
this.dispatchProps = null
this.stateProps = null
this.mergedProps = null
this.haveOwnPropsChanged = true
this.hasStoreStateChanged = true
this.haveStatePropsBeenPrecalculated = false
this.statePropsPrecalculationError = null
this.renderedElement = null
this.finalMapDispatchToProps = null
this.finalMapStateToProps = null
} 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
this.setState({ storeState })
} getWrappedInstance() {
invariant(withRef,
`To access the wrapped instance, you need to specify ` +
`{ withRef: true } as the fourth argument of the connect() call.`
) return this.refs.wrappedInstance
} render() {
const {
haveOwnPropsChanged,
hasStoreStateChanged,
haveStatePropsBeenPrecalculated,
statePropsPrecalculationError,
renderedElement
} = this this.haveOwnPropsChanged = false
this.hasStoreStateChanged = false
this.haveStatePropsBeenPrecalculated = false
this.statePropsPrecalculationError = null if (statePropsPrecalculationError) {
throw statePropsPrecalculationError
} let shouldUpdateStateProps = true
let shouldUpdateDispatchProps = true
if (pure && renderedElement) {
shouldUpdateStateProps = hasStoreStateChanged || (
haveOwnPropsChanged && this.doStatePropsDependOnOwnProps
)
shouldUpdateDispatchProps =
haveOwnPropsChanged && this.doDispatchPropsDependOnOwnProps
} let haveStatePropsChanged = false
let haveDispatchPropsChanged = false
if (haveStatePropsBeenPrecalculated) {
haveStatePropsChanged = true
} else if (shouldUpdateStateProps) {
haveStatePropsChanged = this.updateStatePropsIfNeeded()
}
if (shouldUpdateDispatchProps) {
haveDispatchPropsChanged = this.updateDispatchPropsIfNeeded()
} let haveMergedPropsChanged = true
if (
haveStatePropsChanged ||
haveDispatchPropsChanged ||
haveOwnPropsChanged
) {
haveMergedPropsChanged = this.updateMergedPropsIfNeeded()
} else {
haveMergedPropsChanged = false
} if (!haveMergedPropsChanged && renderedElement) {
return renderedElement
} 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
} if (process.env.NODE_ENV !== 'production') {
Connect.prototype.componentWillUpdate = function componentWillUpdate() {
if (this.version === version) {
return
} // We are hot reloading!
this.version = version
this.trySubscribe()
this.clearCache()
}
} return hoistStatics(Connect, WrappedComponent)
}
}

妈蛋!!!这次有点长,不过不要慌!抓主干!为了更容易理解,我打算从React的生命周期函数的执行顺序讲解!!相信看到我这篇文章的时候,你已经对React有一定的了解,如果还不清楚

React的生命周期函数的执行顺序,看我的正式学习React(三) 和 正式学习React(三)番外篇!或者去官网,或者去谷歌吧。默认我就当大家都知道了!!

1:首先我们要知道connect函数返回的是一个包装类的func,为什么叫它包装类的func,因为它对我们App组件进一步封装,你可以看到的

<Provider store={store}>

<App/>

</Porvider>

其实是:

<Provider store={store}>

<connect>

<App/>

</connect>

</Porvider>

2:connect方法声明如下:

connect([mapStateToProps], [mapDispatchToProps], [mergeProps],[options])

作用:连接 React 组件与 Redux store

连接操作不会改变原来的组件类,反而返回一个新的已与 Redux store 连接的组件类。 【就是我第一点说明的,加了个connect组件,将store和app关联了起来,其实是和connect关联了起来!】

参数

[mapStateToProps(state, [ownProps]): stateProps] (Function): 如果定义该参数,组件将会监听 Redux store 的变化。任何时候,只要 Redux store 发生改变,mapStateToProps 函数就会被调用。该回调函数必须返回一个纯对象,这个对象会与组件的 props 合并。如果你省略了这个参数,你的组件将不会监听 Redux store。如果指定了该回调函数中的第二个参数 ownProps,则该参数的值为传递到组件的 props,而且只要组件接收到新的 props,mapStateToProps 也会被调用。

-----------------------------------------------------------------------------------------------------------------------------

我简单补充一下:为什么组件会监听 Redux store的变化?flux的设计理念就是 dispatch ----》reducer--------》setState。 这个函数是将当前的state映射到props上去.

要想更新视图,使组件渲染成DOM都是最新state和props。必须调用setState,那为什么会调用setState,必然是调用了dispatch,那我们在前面的文章里提过,dispacth的时候,会得到最新 state,并且会

调用subscribe里所有的监听函数。那我们的setState就在这些监听函数里调用!!!

一会你就会看到 componentDidMount()里调用了subcribe(handlechange)  handlechange里最终会调用mapStateToProps,最后 this.setState({ storeState })

-----------------------------------------------------------------------------------------------------------------------------------

[mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function): 如果传递的是一个对象,那么每个定义在该对象的函数都将被当作 Redux action creator,而且这个对象会与 Redux store 绑定在一起,其中所定义的方法名将作为属性名,合并到组件的 props 中。如果传递的是一个函数,该函数将接收一个 dispatch 函数,然后由你来决定如何返回一个对象,这个对象通过 dispatch 函数与 action creator 以某种方式绑定在一起(提示:你也许会用到 Redux 的辅助函数 bindActionCreators())。如果你省略这个 mapDispatchToProps 参数,默认情况下,dispatch 会注入到你的组件 props 中。如果指定了该回调函数中第二个参数 ownProps,该参数的值为传递到组件的 props,而且只要组件接收到新 props,mapDispatchToProps 也会被调用。

[mergeProps(stateProps, dispatchProps, ownProps): props] (Function): 如果指定了这个参数,mapStateToProps() 与 mapDispatchToProps() 的执行结果和组件自身的 props 将传入到这个回调函数中。该回调函数返回的对象将作为 props 传递到被包装的组件中。你也许可以用这个回调函数,根据组件的 props 来筛选部分的 state 数据,或者把 props 中的某个特定变量与 action creator 绑定在一起。如果你省略这个参数,默认情况下返回 Object.assign({}, ownProps, stateProps, dispatchProps) 的结果。

[options] (Object) 如果指定这个参数,可以定制 connector 的行为。

[pure = true] (Boolean): 如果为 true,connector 将执行 shouldComponentUpdate 并且浅对比 mergeProps 的结果,避免不必要的更新,前提是当前组件是一个“纯”组件,它不依赖于任何的输入或 state 而只依赖于 props 和 Redux store 的 state。默认值为 true。

[withRef = false] (Boolean): 如果为 true,connector 会保存一个对被包装组件实例的引用,该引用通过 getWrappedInstance() 方法获得。默认值为 false

------------------------------------------------------------------------------------------------------------------------

3: wrapWithConnect(WrappedComponent){}【主干来了!!!】

return hoistStatics(Connect, WrappedComponent);

hoistStatics不懂没关系,下一篇文章我会讲解。你现在就当它返回Connect,这个Connect是拥有一些WrappedComponent的props的。

这个函数体里我们关心的就是class connect了。

下面我将以生命周期函数的执行顺序讲解 connect!!!!

1:首先我们先去它的constructor里看一看:

             constructor(props, context) {
super(props, context)
this.version = version //来了!来了! context.store也加到了Connect里啦!!这样就保证了Provider和connect里公用了一个store!
this.store = props.store || context.store
//这个函数的代码直接忽略好了
invariant(this.store,
`Could not find "store" in either the context or ` +
`props of "${connectDisplayName}". ` +
`Either wrap the root component in a <Provider>, ` +
`or explicitly pass "store" as a prop to "${connectDisplayName}".`
) //获取当前state
const storeState = this.store.getState() //注意看 this.state,可想而知,之后会在某个地方调用setState 更新视图。整个React-redux项目,将会在connect这里发起更新视图的发起点,因为这里的才有state,子组件我们都是通过props传下去的
this.state = { storeState }
this.clearCache() //这里初始化一些connect的实例属性。里面的具体属性自己看源码,他们的用途,在接下来的用到的时候再讲
}

看完构造函数,我们就最大的收获就是store成为了connect实例的一个属性!并在这里加了state属性!然后初始化了一些属性。。。。。

2:render(){}  这个函数我会讲两次,一次是我们第一次初始化的时候执行,另外就是在Mounted下,我们先看第一次,具体过程大家自己看注释,一步一步走:

  render() {
//这里我们一开始调用了clearCache 给 connect添加了这些属性,并赋予了初始值。
//这里单独用变量取出来用作下面的操作!
const {
haveOwnPropsChanged, //true
hasStoreStateChanged, //true
haveStatePropsBeenPrecalculated, //false
statePropsPrecalculationError, //null
renderedElement // null
} = this //这里给属性还原
this.haveOwnPropsChanged = false
this.hasStoreStateChanged = false
this.haveStatePropsBeenPrecalculated = false
this.statePropsPrecalculationError = null //第一次会跳过。因为statePropsPrecalculationError == null
if (statePropsPrecalculationError) {
throw statePropsPrecalculationError
} //这里都执行render来更新视图了,也很好理解这2个变量。
//肯定是认为应该更新state和proos了
//也要把props分发给子组件了
let shouldUpdateStateProps = true
let shouldUpdateDispatchProps = true //第一次明显跳过 ,因为renderedElement == null
if (pure && renderedElement) {
shouldUpdateStateProps = hasStoreStateChanged || (
haveOwnPropsChanged && this.doStatePropsDependOnOwnProps
)
shouldUpdateDispatchProps =
haveOwnPropsChanged && this.doDispatchPropsDependOnOwnProps
} let haveStatePropsChanged = false
let haveDispatchPropsChanged = false if (haveStatePropsBeenPrecalculated) {
haveStatePropsChanged = true
} else if (shouldUpdateStateProps) { //这里厉害了!因为我们要开始调用我们connect的第一个参数了!
haveStatePropsChanged = this.updateStatePropsIfNeeded()
}
// 第一遍shouldUpdateDispatchProps总是true,haveDispatchPropsChanged总是ture。
if (shouldUpdateDispatchProps) { haveDispatchPropsChanged = this.updateDispatchPropsIfNeeded()
} let haveMergedPropsChanged = true // 第一遍
if (
haveStatePropsChanged ||
haveDispatchPropsChanged ||
haveOwnPropsChanged
) {
haveMergedPropsChanged = this.updateMergedPropsIfNeeded()
} else {
haveMergedPropsChanged = false
} //没变化就返回之前的组件。
if (!haveMergedPropsChanged && renderedElement) {
return renderedElement
} //不然就将mergedProps 当新的props给App
if (withRef) {
this.renderedElement = createElement(WrappedComponent, {
...this.mergedProps,
ref: 'wrappedInstance'
})
} else { this.renderedElement = createElement(WrappedComponent,
this.mergedProps
)
} return this.renderedElement
}

3:componentDidMount(){}

render完成之后就到了这一步。这是生命函数的固定顺序!

里面很简单,就是调用了trySubscribe(){}

trySubscribe这个函数我有必要讲一下:
     trySubscribe() {
// shouldSubscribe 是干嘛的??我们先不管它,假设条件成立!
if (shouldSubscribe && !this.unsubscribe) { //开始订阅函数啦! 这是关键呀,以后我们更新视图全在handleChange里进行
this.unsubscribe = this.store.subscribe(this.handleChange.bind(this)) this.handleChange()
}
} //如果state或者props发生改变,就调用setState。
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
this.setState({ storeState })
} // shouldSubscribe 为false,直接第一次渲染后不再更新视图了 // const shouldSubscribe = Boolean(mapStateToProps)
// mapStateToProps的重要性也凸显出来了!!!

4:如果上面的setState被调用,就到了

shouldComponentUpdate() {

//不纯的默认更新

// this.haveOwnPropsChanged == true  发生在第一次构造connect 的时候,还有就是props被修改的时候。
//
return !pure || this.haveOwnPropsChanged || this.hasStoreStateChanged
} 出场了。。。。。。然后看不是要继续render()

5:componentWillReceiveProps(nextProps){}  当调用了dispath的时候,就会触发setState,然后就可能会触发这个。。。。

6:componentWillUnmount(){}   这个把刚才订阅取消。


总的来说。我们要更加关注render里做的事情,还有trySubscribe里的handle! 第一次流程走通之后,以后每次dispatch,我们就都会执行handle,只有执行了handle才会有后面的生命周期函数执行。

react-redux就是将react和redux结合在一起。 react负责UI, redux负责业务逻辑,

下面给几个图,大家结合着看吧:
最后补充一下 connect 参数的实例:
down voteaccepted
function mapStateToProps(state) {
return {
user: state.app.user
};
} function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(LoginActions, dispatch),
routerActions: bindActionCreators({pushState}, dispatch)
}
} export default connect(mapStateToProps, mapDispatchToProps)(LoginPage);

正式学习React(五) react-redux源码分析的更多相关文章

  1. Redux源码分析之applyMiddleware

    Redux源码分析之基本概念 Redux源码分析之createStore Redux源码分析之bindActionCreators Redux源码分析之combineReducers Redux源码分 ...

  2. Redux源码分析之createStore

    接着前面的,我们继续,打开createStore.js, 直接看最后, createStore返回的就是一个带着5个方法的对象. return { dispatch, subscribe, getSt ...

  3. Redux源码分析之基本概念

    Redux源码分析之基本概念 Redux源码分析之createStore Redux源码分析之bindActionCreators Redux源码分析之combineReducers Redux源码分 ...

  4. Flask框架(五) —— session源码分析

    Flask框架(五) —— session源码分析 目录 session源码分析 1.请求来了,执行__call__方法 2.__call__方法 3.调用__call__方法 3.1.ctx = s ...

  5. Redux源码分析之bindActionCreators

    Redux源码分析之基本概念 Redux源码分析之createStore Redux源码分析之bindActionCreators Redux源码分析之combineReducers Redux源码分 ...

  6. Redux源码分析之combineReducers

    Redux源码分析之基本概念 Redux源码分析之createStore Redux源码分析之bindActionCreators Redux源码分析之combineReducers Redux源码分 ...

  7. Redux源码分析之compose

    Redux源码分析之基本概念 Redux源码分析之createStore Redux源码分析之bindActionCreators Redux源码分析之combineReducers Redux源码分 ...

  8. React事件杂记及源码分析

    前提 最近通过阅读React官方文档的事件模块,发现了其主要提到了以下三个点  调用方法时需要手动绑定this  React事件是一种合成事件SyntheticEvent,什么是合成事件?  事件属性 ...

  9. Java源码解析——集合框架(五)——HashMap源码分析

    HashMap源码分析 HashMap的底层实现是面试中问到最多的,其原理也更加复杂,涉及的知识也越多,在项目中的使用也最多.因此清晰分析出其底层源码对于深刻理解其实现有重要的意义,jdk1.8之后其 ...

  10. Redis学习之zskiplist跳跃表源码分析

    跳跃表的定义 跳跃表是一种有序数据结构,它通过在每个结点中维持多个指向其他结点的指针,从而达到快速访问其他结点的目的 跳跃表的结构 关于跳跃表的学习请参考:https://www.jianshu.co ...

随机推荐

  1. F#(1)

    如果你也会C#,那不妨了解下F#(1):F# 数据类型   简单介绍 F#(与C#一样,念作“F Sharp”)是一种基于.Net框架的强类型.静态类型的函数式编程语言.可以说C#是一门包含函数式编程 ...

  2. Altium Designer (protel) 各版本“故障”随谈

    Altium 的版本很多,每个版本都或多或少有些可容忍或可不容忍的问题,此贴只是希望各位能将遇到的问题写出来,只是希望 给还在使用 altium 的网友一些参考,也希望有些能被 altium 所接受@ ...

  3. WPF学习拾遗(二)TextBlock换行

    原文:WPF学习拾遗(二)TextBlock换行 下午在帮组里的同事解决一个小问题,为了以后方便,把就把它收集一下吧. 新建一个TextBlock作为最基础的一个控件,他所携带的功能相对于其他的控件要 ...

  4. AIX和Linux中wtmp的不同处理方式

    wtmp 记录用户登录和退出事件.它和utmp日志文件相似,但它随着登陆次数的增加,它会变的越来越大,有些系统的ftp访问也在这个文件里记录,同时它也记录正常的系统退出时间,可以用ac和last命令访 ...

  5. Java集合的实现细节—Set集合和Map集合

    Set:代表无序.不可重复的集合 Map:代表key-value对集合,也称为关联数组 从表面上看,Set和Map相似性很少,但实际上可以说Map集合时Set集合的扩展. 1.Set集合和Map集合的 ...

  6. ShellSort Shell排序

    希尔排序(Shell Sort)又称为“缩小增量排序”.是1959年由D.L.Shell提出来的.该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直 ...

  7. Web 前端利器Emmet 的HTML用法总结

    在tutsplus那里看到一篇文章介绍Emmet 的用法,形象的gif图片一目了然,本来想翻译过来的(虽然翻译用法倒不是很难),但搜索发现已经有国人翻译过了,遂直接拿来转载在这里. Emmet 简介 ...

  8. js基础例子

    创建变量 var obj=value; 其中obj是变量名; value表示可能是数字,数组,函数之类的 多变量进行计算 var a1=200,b1='hello',c1=400; var d1=c1 ...

  9. WebService- 使用 CXF 开发 SOAP 服务

    选框架犹如选媳妇,选来选去,最后我还是选了“丑媳妇(CXF)”,为什么是它?因为 CXF 是 Apache 旗下的一款非常优秀的 WS 开源框架,具备轻量级的特性,而且能无缝整合到 Spring 中. ...

  10. 改进的newlisp编译脚本,只需要配置

    前面有一篇Say bye to CMake and Makefile我开始用自己编写的newlisp脚本替代CMake,今天对前面的进行改进. 改进部分是: 1. newlisp armory模块的引 ...