react 组件的生命周期

983 阅读4分钟

一、了解 react 组件的生命周期

  • 什么是组件的生命周期:组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程
  • 钩子函数的作用:为开发人员在不同阶段操作组件提供了时机。
  • 生命周期的意义
    • 有助于理解组件的运行方式
    • 完成更复杂的组件功能
    • 分析组件错误原因等

特别注意:只有 类组件 才有生命周期

二、react 组件的生命周期钩子函数

1、挂载阶段

  • 执行时机:组件创建时(页面加载时)
  • 执行顺序:constructor()→ render()→ componentDidMount()
钩子函数触发时机触发时机
constructor创建组件时,最先执行1.初始化 state 1.创建 ref
render每次组件渲染都会触发渲染 UI (不能调用 setState()
componentDidMount组件挂载(完成DOM渲染)后1. 发送网络请求 2.DOM操作

2、更新阶段

  • 执行时机:1. setState() 2. forceUpdate() 3. 组件接收到新的 props
  • 说明:以上三者任意一种变化,组件就会重新渲染
  • 执行顺序:render()→ componentDidUpdate()
钩子函数触发时机作用
render每次组件渲染都会触发渲染 UI(与 挂载阶段 是同一个 render )
componentDidUpdate组件更新(完成 DOM 渲染)后DOM 操作,可以获取到更新后的DOM内容,不要调用setState

3、卸载阶段

  • 执行时机:组件从页面中消失 钩子函数 | 触发时机 | 作用 | | -------------------- | ------------ | ----------------- | | componentWillUnmount | 组件卸载(从页面中消失) | 执行清理工作(比如:清理定时器等)

三、综合小小示例

1、创建项目、启动、新建文件夹及文件

  • npx create-react-app react-circle
  • cd react-circle
  • yarn start 或 npm start 或 npm run start
  • 新建 src/components/ComCircle.js image.png

2、index.js 入口

import React from 'react'
import ReactDOM from 'react-dom'

import App from './App'

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
)

3、App.js 导入组件

import React from 'react'
// 导入 ComCircle 组件
import ComCircle from './components/ComCircle'
class App extends React.Component {
  render() {
    return <div>
      <ComCircle></ComCircle>
    </div>
  }
}
export default App

4.ComCircle.js 测试

  1. 需求:初始数据 100 ,设置按钮,点击每次加 100 ,加到 300 才更新页面,否则不更新

  2. 目标:探究生命周期钩子函数执行顺序

import React from 'react'
// react 生命周期钩子函数
class ComCircle extends React.Component {
    // state 的写法 1
    // ◆1. constructor	创建组件时,最先执行
    constructor(){
        super()
        this.state = {
            msg: '你好呀,ComCircle',
            num:100
        }
        console.log(this.state.msg,'constructor');// 第一个打印
    }

    // state 的写法 2
    // state = {
    //     msg: '你好呀,ComCircle',
    //     num: 100
    // }

    // ◆2. componentDidMount 相当于 v2 中的 mounted :DOM 加载完毕之后在触发,只会触发一次
    componentDidMount() {
        console.log(this.state.msg, 'componentDidMount');
    }
    // ◆3. componentDidUpdate 相当于 v2 中的 updated:初次进入不会触发
    componentDidUpdate() {
        console.log(this.state.msg, 'componentDidMount');
    }
    // ◆4. shouldComponentUpdate 判断组件是否应该更新了(这个只作了解,有替代方案)
    shouldComponentUpdate(nextProps, nextState) {
        console.log(nextProps, nextState, 'shouldComponentUpdate');
        // 需要判断条件,return 一个 布尔值 不然会报错
        // 满足条件就更新组件;否则不更新
        return nextState.num === 300 ? true : false
    }
    // ◆5. componentWillUnmount 组件从页面消失,比如清理定时器等  
    componentWillUnmount() {
        console.log('componentWillUnmount');
    }
    // 点击事件函数
    changeHandler = () => {
     // setState 的两个作用:1.修改 state;2.更新组件(UI)
        this.setState({
            num: this.state.num + 100
        })
    }
    // ◆6. render 状态发生改变都会触发 render 函数(生命周期钩子函数)
    render() {
        console.log(this.state.msg, 'render');
        return <div>
            我是 ComCircle 组件
            <p>数量:{this.state.num}</p>
            <button onClick={this.changeHandler}>++100</button>
        </div>
    }
}
export default ComCircle

5、当点击按钮加到 400 后 ,页面及后台打印结果

法1:state 写在 constructor 里面

  • 一进入页面 constructorrendercomponentDidMount 依次触发一次
  • 点击按钮到 300 时 render componentDidUpdate 依次触发一次
  • 点击按钮加到 400 及之后, render componentDidUpdate 不再触发(因为shouldComponentUpdate里面有条件)
  • componentWillUnmount 没有触发,因为组件没有消失

image.png

法2:state 没有 写在 constructor 里面

  • 一进入页面 rendercomponentDidMount 依次触发一次
  • 点击按钮到 300 时 render componentDidUpdate 依次触发一次
  • 点击按钮加到 400 及之后, render componentDidUpdate 不再触发(因为shouldComponentUpdate里面有条件)
  • componentWillUnmount 没有触发,因为组件没有消失

image.png

三、纯组件的引入

  • 纯组件:React.PureComponentReact.Component功能相似
  • 区别:PureComponent 内部自动实现了 shouldComponentUpdate 钩子,不需要手动比较
  • 原理:纯组件内部通过分别 对比 前后两次 propsstate 的值,来决定是否重新渲染组件
  • 说明:纯组件内部的对比是 shallow compare(浅层对比)
  • 值类型:比较两个值是否相同(直接赋值即可)
  • 引用类型:只比较对象的引用地址是否相同
  • 注意:只有在性能优化的时候可能会用到纯组件,不要所有的组件都使用纯组件,因为纯组件需要消耗性能进行对比
import React from 'react'
class ComCircle extends React.PureComponent {
    render() {
        return (
        	<div>纯组件</div>
        )
    }
}
export default ComCircle