目录
一、概述
组件的生命周期有助于理解组件的运行方式、完成更复杂的组件功能、分析组件错误原因等
组件的生命周期:组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程
钩子函数的作用:为开发人员在不同阶段操作组件提供了时机
注意:
- 只有 类组件 才有生命周期
1.1 生命周期整体说明图
Vue 生命周期图:
详情可参考:生命周期函数(Vue2.x)
当然除此之外还有:
activated:被 keep-alive 缓存的组件激活时调用,该钩子在服务器端渲染期间不被调用
deactivated:被 keep-alive 缓存的组件失活时调用,该钩子在服务器端渲染期间不被调用
errorCaptured:在捕获一个来自后代组件的错误时被调用。(err: Error, vm: Component, info: string) => ?boolean 此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false
以阻止该错误继续向上传播 详情可参考:errorCaptured
React生命周期图:
可参考:React生命周期
二、挂载(初始化)阶段
执行时机:组件创建时(页面加载时)
执行顺序:
钩子 函数 | 触发时机 | 作用 |
---|---|---|
constructor | 创建组件时,最先执行 | 1. 初始化state 2. 创建Ref等 |
render | 每次组件渲染都会触发 | 渲染UI(注意: 不能调用setState() ) |
componentDidMount | 组件挂载(完成DOM渲染)后 | 1. 发送网络请求 2.DOM操作 |
index.js
import React, { Component } from 'react';
import ReactDom from 'react-dom/client';
export default class App extends Component {
constructor(props) {
super(props);
console.log('1','constructor');
// 作用:
// 1. 提供数据
this.state = {
msg: '23'
}
// 2. 提供 ref
this.inputRef = React.createRef()
// 3. 绑定 this 指向
// 了解,一般都是 handleClick = () => {} 这种写法
// this.handleClick = this.handleClick.bind(this)
}
// render 用于渲染组件结构即渲染页面
render() {
console.log('2', 'render');
return (
<div>
App组件
<button onClick={this.handleClick}>点击</button>
{
// 不能在 render 中调用 setState
// <input type="text" value={this.state.msg} onClick={() => this.setState({})} />
}
</div>
)
}
componentDidMount() {
console.log('3', 'componentDidMount');
}
}
ReactDom.createRoot(document.getElementById('root')).render(<App />)
三、更新阶段
执行时机:1. setState() 2. forceUpdate() 3. 组件接收到新的props
说明:以上三者任意一种变化,组件就会重新渲染
执行顺序:
钩子函数 | 触发时机 | 作用 |
---|---|---|
render | 每次组件渲染都会触发 | 渲染UI(与 挂载阶段 是同一个render) |
componentDidUpdate | 组件更新(完成DOM渲染)后 | DOM操作,可以获取到更新后的DOM内容,不要调用setState |
index.js
import React, { Component } from 'react';
import ReactDom from 'react-dom/client';
import Child from './Child'
export default class App extends Component {
constructor(props) {
super(props);
console.log('1','constructor');
// 作用:
// 1. 提供数据
this.state = {
count: 0
}
// 2. 提供 ref
this.inputRef = React.createRef()
// 3. 绑定 this 指向
// 了解,一般都是 handleClick = () => {} 这种写法
// this.handleClick = this.handleClick.bind(this)
}
// render 用于渲染组件结构即渲染页面
render() {
console.log('2', 'render');
return (
<div>
App组件
<button onClick={this.handleClick}>点击</button>
<p>点击次数:{this.state.count}</p>
<hr/>
{
// 不能在 render 中调用 setState
// <input type="text" value={this.state.msg} onClick={() => this.setState({})} />
}
<Child count={this.state.count}></Child>
</div>
)
}
handleClick = () => {
this.setState({
count: this.state.count + 1,
})
// this.state.count++
// this.forceUpdate() // 强制更新
}
componentDidMount() {
console.log('3', 'componentDidMount');
}
componentDidUpdate() {
console.log('4', 'componentDidUpdate');
}
}
ReactDom.createRoot(document.getElementById('root')).render(<App />)
Child.js
import React, { Component } from 'react'
export default class Child extends Component {
render() {
console.log('子组件的render');
return (
<div>
<h4>点击了,{this.props.count}多次</h4>
</div>
)
}
componentDidUpdate() {
console.log('子组件的componentDidUpdate');
}
}
四、卸载阶段
执行时机:组件从页面中消失
钩子函数 | 触发时机 | 作用 |
---|---|---|
componentWillUnmount | 组件卸载(从页面中消失) | 执行清理工作(比如:清理定时器等) |
index.js
import React, { Component } from 'react';
import ReactDom from 'react-dom/client';
import Child from './Child'
export default class App extends Component {
constructor(props) {
super(props);
console.log('1','constructor');
// 作用:
// 1. 提供数据
this.state = {
count: 0
}
// 2. 提供 ref
this.inputRef = React.createRef()
// 3. 绑定 this 指向
// 了解,一般都是 handleClick = () => {} 这种写法
// this.handleClick = this.handleClick.bind(this)
}
// render 用于渲染组件结构即渲染页面
render() {
console.log('2', 'render');
return (
<div>
App组件
<button onClick={this.handleClick}>点击</button>
<p>点击次数:{this.state.count}</p>
<hr/>
{
// 不能在 render 中调用 setState
// <input type="text" value={this.state.msg} onClick={() => this.setState({})} />
}
{
this.state.count < 6 && <Child count={this.state.count}></Child>
}
</div>
)
}
handleClick = () => {
this.setState({
count: this.state.count + 1,
})
// this.state.count++
// this.forceUpdate() // 强制更新
}
componentDidMount() {
console.log('3', 'componentDidMount');
}
componentDidUpdate() {
console.log('4', 'componentDidUpdate');
}
}
ReactDom.createRoot(document.getElementById('root')).render(<App />)
Child.js
import React, { Component } from 'react'
export default class Child extends Component {
componentDidMount() {
this.timer = setInterval(function(){
console.log('别点了');
}, 1000)
}
render() {
console.log('子组件的render');
return (
<div>
<h4>点击了,{this.props.count}多次</h4>
</div>
)
}
componentDidUpdate() {
console.log('子组件的componentDidUpdate');
}
componentWillUnmount() {
console.log('child点击停止');
clearInterval(this.timer)
}
}