React是很火的前端框架,其最大的特点便是组件化。为了迎娶白富美,当上CEO,走上人生巅峰,对这么火的东东也有了一定的了解,但是对其生命周期一知半解,于是去官方网站瞅了几眼,结合本地实例,和大家共同学习下React组件的生命周期。如果英文比较好的同学可以直接到https://facebook.github.io/react/docs/react-component.html 查看。
创建一个React组件
官网说了,React中有一个React.Component类,这是一个抽象类,我们很少会直接用到它,通常我们写一个子类去继承它,并且在我们的类中至少定义一个render()方法。
上面这个是ES6的写法,当然如果没有用ES6,那么可以向下面这样去写:
组件生命周期
每个组件都有几个生命周期函数,以will为前缀的函数是在发生某些事之前调用,以did为前缀的是在发生某些事之后调用
Mounting
如下这些方法在组件实例被创建和被插入到dom中时被调用。
constructor()
constructor在组件被mounted之前调用,我们的组件继承自React.Component,constructor函数中我们在其他操作前应该先调用super(props),否则this.props将会是undefined。
constructor初始化state的好地方。如果我们不需要初始化state,也不需要bind任何方法,那么在我们的组件中不需要实现constructor函数。
注意下面这种情况,很容易产生bug,我们通常的做法是提升state到父组件,而不是使劲的同步state和props。123456constructor(props) {super(props);this.state = {color: props.initialColor};}componentWillMount()
此方法在mounting之前被立即调用,它在render()之前调用,因此在此方法中setState不会触发重新渲染。此方法是服务器渲染中调用的唯一的生命周期钩子,通常我们建议使用constructor()。- render()
render()方法是react组件必须的,它检查this.props和this.state并且返回一个React元素,我们也可以返回null或false,代表我们不想有任何的渲染。
render()方法应该是一个纯方法,即它不会修改组件的state,在每一次调用时返回同样的结果。它不直接和浏览器交互,如果我们想要交互,应该在componentDidMount()或者其他的生命周期函数里面。 - componentDidMount()
此方法在组件被mounted之后立即被调用,初始化dom节点应该在此方法中,如果需要从远端健在数据,这里是实例化网络请求的好地方,此方法中setState会触发组件重新渲染。
Updating
props和state的改变产生更新。在重新渲染组建时,如下的方法被调用
- componentWillReceiveProps()
一个已经mounted的组件接收一个新的props之前componentWillReceiveProps()被调用,如果我们需要更新state来响应prop的更改,我们可以在此方法中比较this.props和nextProps并使用this.setState来更改state。
注意,即使props没有改变,React也可以调用这个方法,因此如果你只想处理改变,请确保比较当前值和下一个值。当父组件导致你的组件重新渲染时,可能会发生这种情况。
React在组件mounting期间不会调用此方法,只有在一些组件的props可能被更新的时候才会调用。调用this.setState通常不会触发componentWillReceiveProps。 - shouldComponentUpdate()
使用此方法让React知道组件的输出是否不受当前state或props更改的影响。默认行为是在每次state更改时重新渲染组件,在大多数情况下,我们应该默认改行为。
当接收到新的props或state时,shouldComponentUpdate()在渲染之前被调用。默认返回true,对于初始渲染或使用forceUpdate()时,不调用此方法。返回false不会阻止子组件的state更改时,该子组件重新渲染。
如果shouldComponentUpdate()返回false,那么componentWillUpdate(),render()和componentDidUpdate()将不会被调用。在将来,React可能将shouldComponentUpdate()作为提示而不是strict指令,返回仍然可能导致组件重新渲染。 - componentWillUpdate()
当接收新的props或state时,componentWillUpdate()在组件渲染之前被立即调用。使用此函数作为在更新发生之前执行准备的机会。初始渲染不会调用此方法。
注意:这里不能调用this.setState()(如果调用会怎么样?好奇心很重呀,试了一下,会产生死循环,一直更新。。。)。如果我们需要更新state以响应props的更改,我们应该使用componentWillReceiveProps() - render()
render()方法是react组件必须的,它检查this.props和this.state并且返回一个React元素,我们也可以返回null或false,代表我们不想有任何的渲染。
render()方法应该是一个纯方法,即它不会修改组件的state,在每一次调用时返回同样的结果。它不直接和浏览器交互,如果我们想要交互,应该在componentDidMount()或者其他的生命周期函数里面。 - componentDidUpdate()
此函数在更新后立即被调用。初始渲染不调用此方法。
当组件已经更新时,使用此操作作为DOM操作的机会。这也是一个好的地方做网络请求,只要你比较当前的props和以前的props(例如:如果props没有改变,可能不需要网络请求)。
Unmounting
当从dom中移除组件时,这个方法会被调用
- componentWillUnmount()
此函数在组件被卸载和销毁之前被立即调用。在此方法中执行一些必要的清理。例如清除计时器,取消网络请求或者清理在componentDidMount中创建的任何DOM元素。
上手试试
官网说组件生命周期是这样的,但是谁知道对不对呢(当然是对的,但是怀疑的态度还是要有的嘛,主要还是为了加深理解,更好的写React组件)。
See the Pen oBVKWM by wlt (@NsNe) on CodePen.
可以在http://codepen.io(此处不是打广告,只是自己在用这款而已,当然你也可以用其的,比如:jsfiddle等,总有一款适合你,也可以直接f12(chrome),打开console)查看上述代码的console结果。
第一次渲染组件:LifeCycle组件第一次渲染时,打印出(生命周期函数执行):
当组件的props发生改变:当我们点击“改变LifeCycle的props”按钮(组件的props发生改变)时,按理说,这时LifeCycle会调用updating阶段的钩子函数。
当组件的state发生改变:我们在组件内部,点击“改变LifeCycle的state”按钮时(组件的state发生改变),打印如下
当父组件导致子组件重新渲染:当点击“父组件重新渲染,子组件re-render”按钮时(在父组件中改变与子组件无关的state),打印结果如下
当组件被卸载和销毁:打印结果如下:
结语
至此,我们已经很清楚的知道了React组件的生命周期,等到我们写组件的时候就会很清楚的知道代码该往哪里写,哪些地方不能setState等等。大家可以在上述代码中按自己的意愿来修改,加深理解。
文中难免有疏漏,望大家共同交流,批评指正。