上节课我们了解了组件挂载到卸载这一整个生命周期的流程,但是我们好像并没有提到组件更新啊。那么这节课我们就来说一说关于更新。
回顾
在开始这节课之前,我们先来对上节课来做一个简单的回顾:
- 单一组件挂载到卸载整个生命周期中有 5 个生命周期钩子被按顺序调用
constructor
构造器方法- 在组件即将挂载之前调用
componentWillMount
方法 - 调用
render
方法来挂载组件 - 完成组件挂载后立即调用
componentDidMount
- 即将卸载前调用
componentWillUnmount
方法 - 组件中各个生命周期钩子的定义顺序对程序执行没有影响,生命周期钩子执行的顺序依赖与生命周期的流程
以上便是上节课的主要知识点,那么接下来我们便来继续学习今天的课程:
流程图
我们还是要再借助一下流程图的,其实右边这一块其实就是组件的更新过程了,但是这个过程中有三个入口分别是:
- 父组件的
render
setState
forceUpdate
那么我们先走一个我们最熟悉的入口,setState
这个我们用了多少次了都,这儿个就是最基本的更改状态来驱动页面更新嘛,两外两个入口我们之前仿佛根本就没有听过啊。那么好,我们就先从这个setState
开始说起。
我们之前是不是说过,只要我们更新了state
,那么就会重新调用render
,但是实际上呢不仅仅是重新调用了render
,其实还调用了其他的钩子。我们来看一下流程图:
当我们执行完setState
之后,是不是马上到了shouldComponentUpdate
?这个方法我们也没见过,这是什么意思啊?从名字上看就知道:组件是否应该更新。
其实这个方法其实就相当于一个阀门,当我们state
更新之后,相当于程序去问shouldComponentUpdate
方法,我应该更新组件吗?这就相当于一个阀门。如果这个方法返回了false
,那么流程就此截止,页面就不会更新,反之如果返回值是true
那么就会继续往后进行来到了componentWillUpdate
方法。
这个方法我们也没见过,但是读一下名字是什么意思?组件即将更新。这个是不是和我们那个componentWillMount
很类似啊?在更新之前做得准备工作。当这些准备工作做完了之后,直接再调用render
方法来更新组件。
当render
执行完组件也完成了更新,那么立即调用componentDidUpdate
。这个是不是和componentDidMount
的性质一样?当完成什么什么条件之后马上执行什么什么。最后当我们即将卸载的时候就会来调用componentWillUnmount
方法。
那么我们改一下代码看一下效果吧
class Count extends React.Component { state = { count: 0 }; shouldComponentUpdate(){ console.log("Count-shouldComponentUpdate"); return true; } componentWillUpdate(){ console.log("Count-componentWillUpdate"); } componentDidUpdate(){ console.log("Count-componentDidUpdate"); } render() { console.log("Count-render"); const { count } = this.state; return ( <div> <h2>当前点击 {count} 次</h2> <button onClick={this.add}>Add</button> <button onClick={this.unmount}>Unmount</button> </div> ); } add = () => { this.setState({ count: this.state.count + 1 }); } unmount = () => { React.unmountComponentAtNode(document.getElementById("test")); } }
这次我们的代码是不是看着就比之前有条理一点了?初始化状态,然后是生命周期的钩子,然后render
方法,最后是我们自定义的事件回调函数。那么我们看一下效果吧:
我们让shouldComponentUpdate
方法返回true
,然后点击按钮是不是就进入了后面的流程,但是为什么我们在Count-shouldComponentUpdate
之前还打印了Count-render
?我们是不是在挂载组件的时候就要调用一次render
方法啊?所以会额外多出来这一行。那么我们让shouldComponentUpdate
返回false
的话会是什么结果呢?那么我们看一下效果:
页面没有更新,但是调用了shouldComponentUpdate
方法。所以这也印证了我们所说的shouldComponentUpdate
方法其实就是一个阀门,只有当这个阀门打开才能继续后面更新的流程。
但是有人要说了,我们之前从来也没有写过shouldComponentUpdate
方法,那么为什么我们执行了setStae
为什么还是成功更新了呢?因为react
底层会自动把shouldComponentUpdate
方法补上,并且默认返回true
。如果说我们写了这个方法并且让他返回false
,那么页面将无法更新,但是有人说了,如果我写了shouldComponentUpdate
方法,但是我没有返回值会怎么样呢?
我们都知道,每个函数都会默认有返回值是undefined
,只有在你手动return
了之后才会返回你手动return
的值。但是undefined
在这里到底是算true
还是false
呢?我们来试一下呗。把return
这一行注释掉,来看看效果:
出现了错误警告。但是shouldComponentUpdate
成功调用了,而且页面也没有更新,那么说明undefined
算是false
的,但是这个错误却说,shouldComponentUpdate
方法一定要返回true
或者fales
,所以说我们如果要写shouldComponentUpdate
方法的话一定要返回一个明确的bool
值。
以上就是整个组件更新的一个流程。
总结
- 组件完成挂载并执行完了
componentDidMount
之后按顺序执行了 4 个生命周期钩子 - 通过
shouldComponentUpdate
方法判断是否允许更新 - 通过
componentWillUpdate
方法做更新前的准备工作 - 通过
render
方法更新组件 - 更新组件之后立即调用
componentDidUpdate
方法 shouldComponentUpdate
必须返回bool
类型- 如果没有写
shouldComponentUpdate
方法,react
会自动补齐该方法,并且默认该方法返回true
Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.
Link of this article:https://work.lynchow.com/article/lifecycle_setstate_old/