1.概述
意义:组件的生命周期有助于理解组件的运行方式,完成更复杂的组件功能、分析组件错误原因等
组件的生命周期: 组件从被创建到挂载到页面中运行,再到组件不在时卸载的过程,生命周期的每个阶段总是伴随着一些方法调用,这些方法就是生命周期的钩子函数
构造函数的作用:为开发人员在不同阶段操作组件提供了实际
2.生命周期阶段
2.1创建时(挂载阶段)
2.1.1 原理
- 执行时机:组件创建时(页面加载时)
- 执行顺序
2.1.2 效果
2.1.3 代码
//创建时 1、constructor,2、render,3、componentDidMount
// 组件的生命周期
class App extends React.Component{
constructor(props) {
super(props)
console.warn('生命周期钩子函数: constructor')
}
componentDidMount(){
const title = document.getElementById('title')
console.log(title);
console.warn('生命周期钩子函数: componentDidMount')
}
render(){
console.warn('生命周期钩子函数: render')
return(
<div>
<h1 id='title'>统计豆豆被打的次数</h1>
<button id='btn'>打豆豆</button>
</div>
)
}
}
const container = createRoot(document.getElementById('root'))
container.render(<App />)
2.2 更新时
2.2.1 原理
执行时机:setState()、 forceUpdate()、 组件接收到新的props
说明:以上三者任意一种变化,组件就会重新渲染
执行顺序
2.2.2 效果
2.2.3 代码
//更新时1.setState,2.forceUpdate(),3.组件接收到新的props
class App extends React.Component{
constructor(props) {
super(props)
this.state = {
count:0
}
}
handleClick = () => {
this.setState({
count:this.state.count + 1
})
//强制更新
this.forceUpdate()
}
render(){
return(
<div>
<Counter count={this.state.count}/>
<button onClick={this.handleClick}>打豆豆</button>
</div>
)
}
}
class Counter extends React.Component{
render(){
console.warn('子组件生命周期钩子函数: render')
return <h1 id='title'>统计豆豆被打的次数:{this.props.count}</h1>
}
//如果要调用 setState() 更新状态,必须要放在一个if条件中
componentDidUpdate(prevProps){
console.warn('生命周期钩子函数: componentDidUpdate');
if (prevProps.count != this.props.count) {
this.setState({})
}
console.log('上一次的props:',prevProps.count);
//获取DOM
const title = document.getElementById('title')
console.log(title.innerHTML);
}
}
const container = createRoot(document.getElementById('root'))
container.render(<App />)
2.3 卸载时
2.3.1 原理
执行时机:组件从页面中消失
作用:用来做清理操作
2.3.2 效果
2.3.3 代码
class App extends React.Component{
constructor(props) {
super(props)
this.state = {
count:0
}
}
handleClick = () => {
this.setState({
count:this.state.count + 1
})
//强制更新
this.forceUpdate()
}
render(){
return(
<div>
{
this.state.count > 3
? <h1>Game Over</h1>
: <Counter count={this.state.count} handleClick={this.handleClick}/>
}
<button onClick={this.handleClick}>打豆豆</button>
</div>
)
}
}
class Counter extends React.Component{
componentDidMount(){
//开启定时器
this.timeId = setInterval(()=>{
this.props.handleClick()
console.log('自动打豆豆');
},500)
}
render(){
console.warn('子组件生命周期钩子函数: render')
return <h1 id='title'>统计豆豆被打的次数:{this.props.count}</h1>
}
componentWillUnmount(){
//清理定时器
clearInterval(this.timeId)
console.warn('生命周期钩子函数:componentWillUnmount');
}
//如果要调用 setState() 更新状态,必须要放在一个if条件中
componentDidUpdate(prevProps){
console.warn('生命周期钩子函数: componentDidUpdate');
if (prevProps.count != this.props.count) {
this.setState({})
}
console.log('上一次的props:',prevProps.count);
//获取DOM
const title = document.getElementById('title')
console.log(title.innerHTML);
}
}
const container = createRoot(document.getElementById('root'))
container.render(<App />)
2.4 不常用的钩子函数
2.4.1 getDerivedStateFromProps()
getDerivedStateFromProps会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容- 不管原因是什么,都会在每次渲染前触发此方法
2.4.2 shouldComponentUpdate()
- 根据
shouldComponentUpdate()的返回值,判断 React 组件的输出是否受当前 state 或 props 更改的影响。默认行为是 state 每次发生变化组件都会重新渲染 - 当 props 或 state 发生变化时,
shouldComponentUpdate()会在渲染执行之前被调用。返回值默认为 true
2.4.2 getSnapshotBeforeUpdate()
getSnapshotBeforeUpdate()在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给componentDidUpdate()- 此用法并不常见,但它可能出现在 UI 处理中,如需要以特殊方式处理滚动位置的聊天线程等
3.完整源码
import React from 'react';
import {createRoot} from 'react-dom/client'
//创建时 1、constructor,2、render,3、componentDidMount
// 组件的生命周期
// class App extends React.Component{
// constructor(props) {
// super(props)
// console.warn('生命周期钩子函数: constructor')
// }
// componentDidMount(){
// const title = document.getElementById('title')
// console.log(title);
// console.warn('生命周期钩子函数: componentDidMount')
// }
// render(){
// console.warn('生命周期钩子函数: render')
// return(
// <div>
// <h1 id='title'>统计豆豆被打的次数</h1>
// <button id='btn'>打豆豆</button>
// </div>
// )
// }
// }
//更新时1.setState,2.forceUpdate(),3.组件接收到新的props
// class App extends React.Component{
// constructor(props) {
// super(props)
// this.state = {
// count:0
// }
// }
// handleClick = () => {
// this.setState({
// count:this.state.count + 1
// })
// //强制更新
// this.forceUpdate()
// }
// render(){
// return(
// <div>
// <Counter count={this.state.count}/>
// <button onClick={this.handleClick}>打豆豆</button>
// </div>
// )
// }
// }
// class Counter extends React.Component{
// render(){
// console.warn('子组件生命周期钩子函数: render')
// return <h1 id='title'>统计豆豆被打的次数:{this.props.count}</h1>
// }
// //如果要调用 setState() 更新状态,必须要放在一个if条件中
// componentDidUpdate(prevProps){
// console.warn('生命周期钩子函数: componentDidUpdate');
// if (prevProps.count != this.props.count) {
// this.setState({})
// }
// console.log('上一次的props:',prevProps.count);
// //获取DOM
// const title = document.getElementById('title')
// console.log(title.innerHTML);
// }
// }
class App extends React.Component{
constructor(props) {
super(props)
this.state = {
count:0
}
}
handleClick = () => {
this.setState({
count:this.state.count + 1
})
//强制更新
this.forceUpdate()
}
render(){
return(
<div>
{
this.state.count > 3
? <h1>Game Over</h1>
: <Counter count={this.state.count} handleClick={this.handleClick}/>
}
<button onClick={this.handleClick}>打豆豆</button>
</div>
)
}
}
class Counter extends React.Component{
componentDidMount(){
//开启定时器
this.timeId = setInterval(()=>{
this.props.handleClick()
console.log('自动打豆豆');
},500)
}
render(){
console.warn('子组件生命周期钩子函数: render')
return <h1 id='title'>统计豆豆被打的次数:{this.props.count}</h1>
}
componentWillUnmount(){
//清理定时器
clearInterval(this.timeId)
console.warn('生命周期钩子函数:componentWillUnmount');
}
//如果要调用 setState() 更新状态,必须要放在一个if条件中
componentDidUpdate(prevProps){
console.warn('生命周期钩子函数: componentDidUpdate');
if (prevProps.count != this.props.count) {
this.setState({})
}
console.log('上一次的props:',prevProps.count);
//获取DOM
const title = document.getElementById('title')
console.log(title.innerHTML);
}
}
const container = createRoot(document.getElementById('root'))
container.render(<App />)