资讯专栏INFORMATION COLUMN

React-Redux源码剖析

Shimmer / 3146人阅读

摘要:为了能够更好的使用这个工具,今天就对它进行一下源码剖析。它内部的关键代码是在不指定的时候等于,这就意味着的源码剖析到此结束,谢谢观看当然如果指定了剖析就还得继续。好了,源码剖析到此结束,谢谢观看

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方法。

好了,源码剖析到此结束,谢谢观看!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80034.html

相关文章

  • 我的源码阅读之路:redux源码剖析

    摘要:到月底了,小明的爸爸的单位发了工资总计块大洋,拿到工资之后第一件的事情就是上交,毫无疑问的,除非小明爸爸不要命了。当小明的爸爸收到这个通知之后,心的一块大石头也就放下来了。下面我们正式开始我们的源码阅读之旅。 前言 用过react的小伙伴对redux其实并不陌生,基本大多数的React应用用到它。一般大家用redux的时候基本都不会单独去使用它,而是配合react-redux一起去使用...

    CloudwiseAPM 评论0 收藏0
  • Redux源码剖析

    摘要:的存在是为了避免在执行过程中,发生改变,导致错误。保证的修改不会影响。在内部关键代码是第一行用来调用,并将执行的结果赋给。符合这个标准的会被放入中。以上基本是的全部关键代码剖析,简单而强大。 前面写了《React组件性能优化》《Redux性能优化》《React-Redux性能优化》,但是都没有从这些框架的实现上讲为什么?这次就从源码上来分析一下这些框架的实现原理,以更深入的理解这些框架...

    Yangder 评论0 收藏0
  • 解密Redux: 从源码开始

    摘要:接下来笔者就从源码中探寻是如何实现的。其实很简单,可以简单理解为一个约束了特定规则并且包括了一些特殊概念的的发布订阅器。新旧中存在的任何都将收到先前的状态。这有效地使用来自旧状态树的任何相关数据填充新状态树。 Redux是当今比较流行的状态管理库,它不依赖于任何的框架,并且配合着react-redux的使用,Redux在很多公司的React项目中起到了举足轻重的作用。接下来笔者就从源码...

    remcarpediem 评论0 收藏0
  • 纯Redux原理分析

    摘要:调用链中最后一个会接受真实的的方法作为参数,并借此结束调用链。总结我们常用的一般是除了和之外的方法,那个理解明白了,对于以后出现的问题会有很大帮助,本文只是针对最基础的进行解析,之后有机会继续解析对他的封装 前言 虽然一直使用redux+react-redux,但是并没有真正去讲redux最基础的部分理解透彻,我觉得理解明白redux会对react-redux有一个透彻的理解。 其实,...

    sumory 评论0 收藏0
  • FE.SRC-React实战与原理笔记

    摘要:异步实战状态管理与组件通信组件通信其他状态管理当需要改变应用的状态或有需要更新时,你需要触发一个把和载荷封装成一个。的行为是同步的。所有的状态变化必须通过通道。前端路由实现与源码分析设计思想应用是一个状态机,视图与状态是一一对应的。 React实战与原理笔记 概念与工具集 jsx语法糖;cli;state管理;jest单元测试; webpack-bundle-analyzer Sto...

    PumpkinDylan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<