React的生命周期

155 阅读3分钟

「回顾2022,展望2023,我正在参与2022年终总结征文大赛活动

什么是生命周期

组件从 被创建 到 被销毁 的过程称为组件的生命周期。

React生命周期的三个阶段

React的生命周期分为三个阶段:挂载期(也叫实例化期)、更新期(也叫存在期)、卸载期(也叫销毁期)。在每个周期中React都提供了一些钩子函数。
生命周期的描述如下:
挂载期:一个组件实例初次被创建的过程。
更新期:组件在创建后再次渲染的过程。
卸载期:组件在使用完后被销毁的过程。

生命周期方法

常见方法图

00.png

可查看react生命周期图片链接

完整方法图

11.png

可查看react生命周期图片链接

挂载阶段

  • constructor: 构造函数,最先被执行,我们通常在构造函数里初始化state对象或者给自定义方法绑定this
  • getDerivedStateFromProps: static getDerivedStateFromProps(nextProps, prevState),这是个静态方法,当我们接收到新的属性想去修改state,可以使用getDerivedStateFromProps
  • render: render函数是纯函数,只返回需要渲染的东西,不应该包含其它的业务逻辑,可以返回原生的DOM、React组件、Fragment、Portals、字符串和数字、Boolean和null等内容
  • componentDidMount: 组件装载之后调用,此时可以获取到DOM节点并操作,比如对canvas,svg的操作,服务器请求,订阅都可以写在这个里面,但是记得在componentWillUnmount中取消订阅。

更新阶段

  • getDerivedStateFromProps: 此方法在更新个挂载阶段都可能会调用
  • shouldComponentUpdate: shouldComponentUpdate(nextProps, nextState),有两个参数nextPropsnextState,表示新的属性和变化之后的state,返回一个布尔值,true表示会触发重新渲染,false表示不会触发重新渲染,默认返回true,我们通常利用此生命周期来优化React程序性能
  • render: 更新阶段也会触发此生命周期
  • getSnapshotBeforeUpdate: getSnapshotBeforeUpdate(prevProps, prevState),这个方法在render之后,componentDidUpdate之前调用,有两个参数prevPropsprevState,表示之前的属性和之前的state,这个函数有一个返回值,会作为第三个参数传给componentDidUpdate,如果你不想要返回值,可以返回null,此生命周期必须与componentDidUpdate搭配使用
  • componentDidUpdate: componentDidUpdate(prevProps, prevState, snapshot),该方法在getSnapshotBeforeUpdate方法之后被调用,有三个参数prevPropsprevStatesnapshot,表示之前的props,之前的state,和snapshot。第三个参数是getSnapshotBeforeUpdate返回的,如果触发某些回调函数时需要用到 DOM 元素的状态,则将对比或计算的过程迁移至getSnapshotBeforeUpdate,然后在 componentDidUpdate中统一触发回调或更新状态。

卸载阶段

  • componentWillUnmount: 当组件被卸载或者销毁了就会调用,我们可以在这个函数里去清除一些定时器,取消网络请求,清理无效的DOM元素等垃圾清理工作。

代码演示

<!-- 生命周期 -->

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://unpkg.com/react@17.0.2/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js" crossorigin></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <title>Document</title>
</head>

<body>
    <div id="root"></div>

    <script type="text/babel">
        class Count extends React.Component {
            constructor(props) {
                console.log('constructor');
                super(props);
                this.state = {
                    count: 0
                }
            }

            add = () => {
                this.setState({
                    count: this.state.count + 1
                })
            }

            death = () => {
                ReactDOM.unmountComponentAtNode(document.getElementById('root'))    
                // React提供的方法 把该容器root的子节点全部移除
            }

            force = () => {
                this.forceUpdate()
            }


            // 得到一个额外的状态
            static getDerivedStateFromProps(props, state) {
            // 将父组件传过来的props和自己组件的state进行合并
            
                console.log(' getDerivedStateFromProps', props, state);
                return null
            }

            // 组件挂载完毕
            componentDidMount() {
                console.log('componentDidMount');
            }

            // 控制组件更新的'阀门'
            shouldComponentUpdate() {   // 人为的控制组件是否允许更新
                console.log('shouldComponentUpdate');
                return true;   // 为false时,不会执行后面的render(),组件不更新
            }

            // 更新之前获取快照   快照的意思就是相当于在某个时间点截图,截图里的数据在该时间点后变更了,
            //但是因为你快照过,就相当于证明你曾经有过这些数据 
            getSnapshotBeforeUpdate() {
                console.log('getSnapshotBeforeUpdate');
                return 'hello'  // return的值传给 componentDidUpdate 作为参数
            }

            // 组件更新完毕
            componentDidUpdate(preProps, preState, snapshotValue) {
                console.log('componentDidUpdate', preProps, preState, snapshotValue);
            }


            // 组件卸载  就是这个组件跳到别的组件,这个组件就会被卸载掉
            componentWillUnmount() {
                console.log('componentWillUnmount');
            }

            render() {
                console.log('render');
                const { count } = this.state
                return (
                    <div>
                        <h2>当前求和为:{count}</h2>
                        <button onClick={this.add}>点我+1</button>
                        <button onClick={this.death}>卸载组件</button>
                        <button onClick={this.force}>不更改任何状态数据,强制更新一下</button>
                    </div>
                )
            }
        }

        ReactDOM.render(<Count count={100} />, document.getElementById('root'))
    </script>
</body>

</html>