一张图读懂React组件生命周期,及组件更新的注意点

广告位招租
扫码页面底部二维码联系

看了网上很多资料,大部分文章在谈Reac【本文受版权保护】著作权归作者所有,禁止商业用途转载。t的组件生命周期时,都把所有的组件周期函著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】数给讲一遍,但却很难把握。要读懂reac【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】t的生命周期,必须要靠我下面提供的这张图原创内容,盗版必究。【原创内容,转载请注明出处】。我们在理解生命周期时,不应该把重点放在【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】那些生命周期函数上,这些函数什么时候调用【转载请注明来源】【原创不易,请尊重版权】,甚至掉不掉用,完全取决于他们出现在生命【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】周期的哪一个节点上。因此,我们应该从组件转载请注明出处:www.tangshuang.net原创内容,盗版必究。真正的生命周期重新去理解这些函数,而非从本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。函数反过来理解周期。

【原创内容,转载请注明出处】【作者:唐霜】著作权归作者所有,禁止商业用途转载。

React组件生命周期函数调用顺序示意图

【作者:唐霜】转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net【作者:唐霜】

那些资料除了错误的讲解思路之外,还有一个原创内容,盗版必究。原创内容,盗版必究。不足就是把生命周期仅限于单个组件,而非父【原创不易,请尊重版权】【作者:唐霜】子组件系统。所以,当遇到父组件更新,子组著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】件的周期如何的问题时,就很难理解。这张示【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】意图表达了父子组件系统里面,组件生命周期【转载请注明来源】【原创内容,转载请注明出处】中对周期函数的调用顺序。

【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】

生命周期三阶段著作权归作者所有,禁止商业用途转载。

【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。

react的组件生命存在三个阶段:创建期著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net、存活期、清理期。事后来看,创建期和清理著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。期很容易搞懂。真正难懂的,是存活期内,对本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】试图的更新问题。即当你在代码中使用thi【作者:唐霜】【本文受版权保护】s.setState时,界面的更新带来的【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】一系列周期函数是否调用、调用顺序的问题。

本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】未经授权,禁止复制转载。【本文首发于唐霜的博客】

创建期本文版权归作者所有,未经授权不得转载。

【转载请注明来源】本文作者:唐霜,转载请注明出处。【本文受版权保护】未经授权,禁止复制转载。【本文受版权保护】

即一个ES6类的实例化过程。当然,rea本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。ct的组件有简写的方法,但我们这里普遍讨转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。论的是,用ES6 class语法撰写的组本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。件的代码流程。我们把目光聚焦到“子组件”未经授权,禁止复制转载。【转载请注明来源】上,现在我们来看一个组件的创建过程。

本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】【未经授权禁止转载】本文作者:唐霜,转载请注明出处。

我们使用一个组件,往往是把它引入之后,使【未经授权禁止转载】【本文首发于唐霜的博客】用directive的方式,用jsx语法著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。直接在render函数中使用,如下:

本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】未经授权,禁止复制转载。
import MyComponent from './my-component'

export default class ParentComponent extends React.Component {
  render() {
    return (
      <div>
        <MyComponent />
      </div>
    )
  }
}

当父组件被实例化时,会按照jsx语法,实转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net例化MyComponent作为当前父组件【作者:唐霜】转载请注明出处:www.tangshuang.net的子组件实例。所谓“实例”是指一个抽象类【原创不易,请尊重版权】未经授权,禁止复制转载。的具体表现,也就是说同一个类可以有多个实【本文受版权保护】【本文首发于唐霜的博客】例,甚至在一个父组件里面也可以有多个实例【作者:唐霜】【转载请注明来源】。既然子组件在父组件中是以实例的方式存在【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】,那么就必然有实例化的过程。因此,当父组转载请注明出处:www.tangshuang.net【转载请注明来源】件实例化的时候,子组件也被实例化出来。

【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】【本文受版权保护】【关注微信公众号:wwwtangshuangnet】

我们回到图中,当父组件的生命周期进入到实【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net例化的render函数之后,react会【未经授权禁止转载】【版权所有,侵权必究】以内部的机制去实例化子组件。而子组件和孙本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net组件之间的关系,和父组件与子组件的关系是本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】一摸一样的,因此,图中并没有描画孙组件的【转载请注明来源】【原创不易,请尊重版权】生命周期调用情况。但是可以肯定的是,当真转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net正的DOM渲染之后,子组件的compon【原创不易,请尊重版权】【未经授权禁止转载】entDidMount函数会比父组件的更转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】早执行。当然,组件是一个相对封闭的单位,【原创内容,转载请注明出处】【未经授权禁止转载】因此周期函数不应该对上下级组件的did函【作者:唐霜】原创内容,盗版必究。数有任何影响。

【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。【作者:唐霜】

存活期【版权所有】唐霜 www.tangshuang.net

【作者:唐霜】转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。

而实际上,componentDidMou【转载请注明来源】本文作者:唐霜,转载请注明出处。nt函数的半只脚已经在组件的存活期内了。【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net一旦通过render函数之后,react【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。会把Virtual DOM渲染为真实的D【转载请注明来源】【作者:唐霜】OM,这时就已经是存活期了。而compo转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】nentDidMount函数是在DOM被未经授权,禁止复制转载。【本文首发于唐霜的博客】渲染出来之后执行的,所以说它已经半只脚在未经授权,禁止复制转载。未经授权,禁止复制转载。存活期内了。

【原创内容,转载请注明出处】【原创不易,请尊重版权】【作者:唐霜】【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】

而一旦组件进入存活期,就可能发生更新的情【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。况,而且更新次数是无限制的。有三种情况下转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net,组件视图会被更新,一种是组件自己调用t原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。his.setState,一种是组件自己【未经授权禁止转载】原创内容,盗版必究。调用this.forceUpdate,还【版权所有,侵权必究】【未经授权禁止转载】有一种是父组件更新(父组件调用this.【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】setState或this.forceU【未经授权禁止转载】【原创不易,请尊重版权】pdate或祖组件更新带来的props更本文作者:唐霜,转载请注明出处。【未经授权禁止转载】改)时导致自己的props被更改。

【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net【作者:唐霜】

让我们把目光集中在上图中的子组件的存活期本文作者:唐霜,转载请注明出处。【转载请注明来源】

【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】【本文首发于唐霜的博客】【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】

react组件存活期的函数调用顺序示意图

【转载请注明来源】本文作者:唐霜,转载请注明出处。【转载请注明来源】

创建期过去之后,创建期函数不会再被调用。【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。但componentDidMount中的原创内容,盗版必究。本文作者:唐霜,转载请注明出处。某些操作将常驻内存,比如绑定了事件,还有原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】一些操作可以带来界面的更新,即在comp【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。onentDidMount中调用this【作者:唐霜】【作者:唐霜】.setState。

【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net

上面这幅小图展示了组件更新的三种方式,最【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net常发生的是父组件传递的props发生变化原创内容,盗版必究。【本文首发于唐霜的博客】(父组件的render函数中),此时子组【本文受版权保护】原创内容,盗版必究。件会首先调用componentWillR转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】eceiveProps,这个函数的作用主原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。要是在组件发生变化之前,对当前的stat【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.nete(甚至传递来的props,虽然不提倡)未经授权,禁止复制转载。【本文受版权保护】进行修改,即在这个函数内调用this.s本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】etState。但是非常重要的一点是,在componentWillReceiv【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。eProps中调用setState不会引未经授权,禁止复制转载。未经授权,禁止复制转载。起界面的重绘,无论父组件传递的props本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】是否发生变化都会经过componentW【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.netillReceiveProps函数,只要父组件重新执行了render函数。

【作者:唐霜】【转载请注明来源】【版权所有,侵权必究】转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】

另一种是调用setState,即在子组件【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】自己内部调用this.setState,【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。这时不会调用componentWillR【转载请注明来源】【原创不易,请尊重版权】eceiveProps函数。因此非常明显【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。的一点,当componentWillRe【作者:唐霜】本文版权归作者所有,未经授权不得转载。ceiveProps函数被调用时,明显是【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。来自父组件的变化。因此,可以在compo转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。nentWillReceiveProps本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net函数内做一些记录,以此来判定组件的变化是【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。否来自父组件。

【本文首发于唐霜的博客】【版权所有,侵权必究】【作者:唐霜】原创内容,盗版必究。

以上两种情况的更新,都会紧接着执行sho【本文首发于唐霜的博客】【原创不易,请尊重版权】uldComponentUpdate函数【转载请注明来源】未经授权,禁止复制转载。,这个函数非常重要,它决定了更新动作是否【作者:唐霜】转载请注明出处:www.tangshuang.net继续往下走。如果返回false,那么就不【转载请注明来源】未经授权,禁止复制转载。会在执行下面的那些函数,当然,界面也不会本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net被更新,因此,它是优化性能的关键。由于s【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。tate和props的变化都会经过这里,【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。所以它有两个参数:nextProps和n未经授权,禁止复制转载。【本文首发于唐霜的博客】extState,它们各自对应不同的更新本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。方式。

【未经授权禁止转载】【版权所有,侵权必究】转载请注明出处:www.tangshuang.net

还有一种是在组件内调用this.forc著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】eUpdate,不需要经过shouldC本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。omponentUpdate,force转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。Update直接忽略shouldComp【本文受版权保护】【本文首发于唐霜的博客】onentUpdate,一定会更新组件。

原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。【转载请注明来源】原创内容,盗版必究。

如果有机会进入componentWill【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】Update函数,那么当前组件的this.props和th【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。is.state都会是新的,你现在可以使转载请注明出处:www.tangshuang.net原创内容,盗版必究。用this.props或this.sta【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】te得到新的值了 可以获取 nextProps 和 ne著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netxtState。它们会被用到render函数中。【原创内容,转载请注明出处】

转载请注明出处:www.tangshuang.net【转载请注明来源】【版权所有,侵权必究】

经过render函数之后,compone转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】ntDidUpdate和componen转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】tDidMount很像,也是在渲染完(即【未经授权禁止转载】【本文首发于唐霜的博客】使界面没有发生变化)之后被调用。但是不同本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】的是,componentDidMount中可以本文作者:唐霜,转载请注明出处。【作者:唐霜】调用this.setState,而com【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.netponentDidUpdate中几乎不可未经授权,禁止复制转载。【作者:唐霜】。从上面的图中你可以看出setState【作者:唐霜】原创内容,盗版必究。之后componentDidUpdate【原创不易,请尊重版权】未经授权,禁止复制转载。函数会被调用,如果你在component未经授权,禁止复制转载。未经授权,禁止复制转载。DidUpdate中再调用setStat著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。e,那么就会造成死循环。当然,从逻辑上讲,如果shouldCom本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】ponentUpdate返回为false【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net,那么不会进入componentDidU未经授权,禁止复制转载。原创内容,盗版必究。pdate,因此在绝对保证没有问题的情况【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】下,也是可以使用setState的,只不【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】过你要极其极其小心。

【作者:唐霜】转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。

销毁期本文版权归作者所有,未经授权不得转载。

本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】【本文受版权保护】转载请注明出处:www.tangshuang.net

在销毁期,开发者经常做的事是将compo【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】nentWillUnmount中设置的监【原创内容,转载请注明出处】【原创内容,转载请注明出处】听或异步动作取消掉,已防止监听回调被调用【作者:唐霜】【转载请注明来源】时,发现当期组件已经被销毁了,这样会报错本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。

【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。

其实问题在于,组件什么时候会被销毁?我们本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。开发的时候,几乎很少自己去销毁一个组件。转载请注明出处:www.tangshuang.net原创内容,盗版必究。组件的销毁隐匿于父组件的render函数原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。中。当父组件执行render函数时,某些【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。情况下,Virtual DOM中的某些节【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。点经过diff,发现已经不存在了,因此会【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】被销毁,而这个节点正好是一个组件的话,那【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net么组件就会被销毁,而组件的compone转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】ntWillUnmount方法会被调用。【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。我们来看下例子:

未经授权,禁止复制转载。【版权所有,侵权必究】【转载请注明来源】
class M extends Component {
  render() {
    return (
      <div>
        {this.props.has ? <MyComponent /> : null}
      </div>
    )
  }
}

当父组件发生更新,而父组件的this.p本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netrops.has为false时,MyCo本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。mponent这个组件就会被销毁,它的c【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。omponentWillUnmount就【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net会被调用。

转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】

组件更新的注意点【原创内容,转载请注明出处】

【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】

经过上面的讲解,相信你已经从糊里糊涂变得本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】更加清晰了,但是,在实际开发中,你可能还著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】会遇到一些问题,特别是在涉及到主动更新界本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net面的时候。我们不妨来一一探讨一下。

【转载请注明来源】未经授权,禁止复制转载。【版权所有,侵权必究】【本文首发于唐霜的博客】

setState是异步的未经授权,禁止复制转载。

【版权所有,侵权必究】【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。

这已经被无数人强调过了。当你要进行一项操原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】作,更改state之后想要获取它的值,一转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】定要知道,你不可能马上得到更新后的值:

【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net
let count = this.state.count // 9
this.setState({ count: count + 1 })
console.log(this.state.count) // 9

这种不可靠的操作让我们在一些开发过程中非本文作者:唐霜,转载请注明出处。原创内容,盗版必究。常苦恼。因为异步性,所以react提供了【转载请注明来源】原创内容,盗版必究。callback方法,让你在state被【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。更新之后可以获得新的state:

原创内容,盗版必究。【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。
let count = this.state.count // 9
this.setState({ count: count + 1 }, () => {
  console.log(this.state.count) // 10
})

但是这样的操作显得很傻。因此,遇到这种情【版权所有】唐霜 www.tangshuang.net【本文受版权保护】况,你需要非常小心,不一定非得使用set【版权所有,侵权必究】【作者:唐霜】State,你可以有自己的数据管理器,比转载请注明出处:www.tangshuang.net原创内容,盗版必究。如自己在组件上挂载一个this.$dat未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。a来进行数据管理。从这一点上来讲,set【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】State对我来说,更像是update方著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。法,也就是界面的更新触发函数。

【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】

父组件中异步加载数据【作者:唐霜】

【转载请注明来源】【版权所有,侵权必究】转载请注明出处:www.tangshuang.net【版权所有,侵权必究】

重点是“父组件中”,异步加载数据是一个非本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net常麻烦的事,因为react的DOM是在第【本文受版权保护】本文作者:唐霜,转载请注明出处。一次实例化的时候被渲染的,而异步加载数据转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】只能放在componentDidMoun【未经授权禁止转载】未经授权,禁止复制转载。t中,或者你可以有更好的办法把异步加载操未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net作放到componentWillMoun著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】t中,但是无论如何,你不可能在创建期实现原创内容,盗版必究。本文作者:唐霜,转载请注明出处。把数据渲染出来,只能在component【原创不易,请尊重版权】未经授权,禁止复制转载。DidMount中使用setState把【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。数据塞回去,通过更新界面来展示数据。

【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。原创内容,盗版必究。转载请注明出处:www.tangshuang.net

我在这篇文章里面提到,组件分为两种,一种未经授权,禁止复制转载。【版权所有,侵权必究】是业务组件,一种是纯UI组件。而数据加载转载请注明出处:www.tangshuang.net【未经授权禁止转载】一定是业务组件的事,但展示数据往往又是U本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。I组件实现的。那么这里对UI组件就有一个【原创不易,请尊重版权】原创内容,盗版必究。要求:

【转载请注明来源】【版权所有】唐霜 www.tangshuang.net【转载请注明来源】【转载请注明来源】【未经授权禁止转载】

UI组件输入相同的props,一定能得到【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net相同的界面,而且是同步阻塞的【原创不易,请尊重版权】【原创内容,转载请注明出处】

未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】
【版权所有,侵权必究】【转载请注明来源】【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。

要求UI组件同步阻塞,就必须要求UI组件【本文受版权保护】【版权所有】唐霜 www.tangshuang.net的render中使用this.props原创内容,盗版必究。【原创不易,请尊重版权】.data作为数据源,而不能使用this未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】.state.data进行内部可变的操作著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】。这一点很难理解,我们反其道而行,看下如【本文受版权保护】著作权归作者所有,禁止商业用途转载。果一个UI组件使用state.data的【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net案例:

转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。【作者:唐霜】原创内容,盗版必究。
export default MyUI extends React.Component {
  construtor(props) {
    super(props)
    this.state = {
      data: []
    }
  }
  componentDidMount() {
    let data = this.props.data
    let newData = []
    data.forEach(item => {
      newData.push({ name: item.n, age: item.a })
    })
    this.setState({ data: newData })
  }
  render() {
    return <Table data={this.state.data} /> // 假设我们有一个Table组件
  }
}

我们在父组件中这样使用它:著作权归作者所有,禁止商业用途转载。

【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net
export default MyData extends React.Component {
  constructor(props) {
    super(props)
    this.state = { data: [] }
  }
  componentDidMount() {
    fetch(...).then(res => res.json).then(data => this.setState({ data })) // 异步获取数据
  }
  render() {
    return <MyUI data={this.state.data} />
  }
}

父组件作为业务组件,这样是完全没有问题的【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。。我们来看子组件,当子组件实例化之后,c未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】omponentDidMount被执行,【版权所有,侵权必究】【作者:唐霜】但是实例化的时候,父组件数据根本没有回来【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。,所以子组件的state.data是空的转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。。而当父组件的数据回来之后,本来想通过s【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】etState来触发子组件的重新渲染,结【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。果子组件没有任何变化。这是因为,子组件中【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。使用state.data作为数据源,co原创内容,盗版必究。【作者:唐霜】mponentDidMount函数被执行本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】之后,数据源就没有发生过任何变化。我们可本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。以通过componentWillRece【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】iveProps来进行修复,前面已经讲过原创内容,盗版必究。本文作者:唐霜,转载请注明出处。了,可以使用setState:

转载请注明出处:www.tangshuang.net【作者:唐霜】【版权所有,侵权必究】
export default MyUI extends React.Component {
  construtor(props) {
    super(props)
    this.state = {
      data: []
    }
  }
  componentWillReceiveProps(nextProps) {
    this.setState({ data: nextProps.data }) // 不会触发更新视图,但state已经发生改变
  }
  componentDidMount() {
    let data = this.props.data
    let newData = []
    data.forEach(item => {
      newData.push({ name: item.n, age: item.a })
    })
    this.setState({ data: newData })
  }
  render() {
    return <Table data={this.state.data} /> // 假设我们有一个Table组件
  }
}

上面的修改看似合理,但是又出现了新的问题【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】,我们希望对新传过来的数据进行处理之后才未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。给state.data,因此,又必须把数本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】据处理的部分单独成一个独立的方法:

著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net
export default MyUI extends React.Component {
  construtor(props) {
    super(props)
    this.state = {
      data: []
    }
  }
  dealWithData(data) {
    let newData = []
    data.forEach(item => {
      newData.push({ name: item.n, age: item.a })
    })
    return newData
  }
  componentWillReceiveProps(nextProps) {
    this.setState({ data: this.dealWithData(nextProps.data) })
  }
  componentDidMount() {
    this.setState({ data: this.dealWithData(this.props.data)})
  }
  render() {
    return <Table data={this.state.data} /> // 假设我们有一个Table组件
  }
}

这一下就改了一大堆代码。而如果我们把这一本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】大堆事情都交给父组件去做,UI组件在渲染本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。的时候直接使用this.props.da本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.netta作为数据源,而非经过处理的this.【本文受版权保护】著作权归作者所有,禁止商业用途转载。state.data,那么事情会变得非常本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。简单。

【转载请注明来源】未经授权,禁止复制转载。原创内容,盗版必究。【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】

如果你的界面上,还使用了一个loadin本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。g效果,那么最好把数据的异步加载放到lo【原创内容,转载请注明出处】【未经授权禁止转载】ading组件的同级组件中,这样就可能出【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】现数据的获取,和数据的展示,两个之间差了【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】好几层组件,这时就可以考虑使用redux本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net了。

原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】

2017-10-04 12114

为价值买单,打赏一杯咖啡

本文价值121.14RMB
已有3条评论
  1. xinhan 2019-09-04 13:41

    如果有机会进入componentWillUpdate函数,那么当前组件的this.props和this.state都会是新的. 疑问:这个时候props,state 应该还没更新,只能从两个参数来拿 nextProps,nextState。

    • 否子戈 2019-09-10 20:14

      谢谢指出
      不过这篇文章写的比较早,新版本的 react 周期函数已经发生了变化,包括渲染机制的时间顺序也变化,这篇文章已经不适用了

      • xinhan 2019-09-11 10:02

        对比了之前的版本,确实很大变化,有些钩子未来也即将作废,非常感谢大佬的分享,受益良多,文章拜读了很多遍!