一、生命周期概述
- 生命周期: 组件从创建到加载运行再到不用卸载的整个过程就是生命周期 (创建 --> 加载运行 --> 卸载)
- 掌握组件生命周期有助于我们理解组件的运行方式,完成更复杂的功能,分析组件错位u原因以及解决错误
- 生命周期的每个阶段中都有一些方法调用,这些方法就是生命周期的钩子函数,钩子函数能够实现更多的功能
只有类组件才有生命周期
二、生命周期的三个阶段
1、创建阶段
执行时机:只要页面一经加载,组件一旦被渲染,下面的三个钩子函数就会执行
顺序执行: constructor —> render —> componentDidMount
import React from 'react'
import ReactDOM from 'react-dom'
class Hello extends React.Component {
constructor (props) {
super(props)
console.log('执行了constructor 函数')
}
render () {
console.log('执行了 render 函数')
return (
<div id="title">Hello 组件</div>
)
}
componentDidMount () {
console.log('执行了 componentDidMount 函数')
const title = document.querySelector('#title')
console.log(title)
}
}
ReactDOM.render(<Hello />, document.getElementById('root'))
钩子函数 | 触发时机 | 作用 |
---|---|---|
constructor | 创建组件时 | 1、初始化 state;2、使用 bind 修改方法的this指向 |
render | 每次渲染组件时 | 渲染页面 (不能调用 setState 方法) |
componentDidMount | 渲染完成后 | 1、发送网络请求;2、DOM操作 |
2、更新阶段
更新时会顺序执行两个函数: render —> componentDidUpdate
有三种情况会更新组件:
- new props:组件接收到新属性的时候render 会重新渲染, props 的值会发生改变
- forceUpdate(): 调用 forceUpdate() 强制进行更新
- setState(): 调用了setState 方法更新数据
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
constructor () {
super()
this.state = {
count:0
}
//console.log('执行了constructor 函数')
}
handleClick = () => {
// 调用 forceUpdate 方法能够强制更新
// this.forceUpdate()
// 调用 setState 方法更新数据后触发更新
this.setState({
count:this.state.count + 1
})
}
render () {
console.log('执行了 render 函数')
return (
<div>
<Counter count={this.state.count}/>
<button onClick={this.handleClick}>打满满</button>
</div>
)
}
componentDidMount () {
console.log('执行了 componentDidMount 函数')
}
componentDidUpdate () {
console.log('执行了 componentDidUpdate 函数')
}
}
class Counter extends React.Component{
render(){
return <h1>统计打满满的次数:{this.props.count}</h1>
}
}
ReactDOM.render(<App />, document.getElementById('root'))
钩子函数 | 触发时机 | 作用 |
---|---|---|
render | 每次渲染 | 渲染页面 |
componentDidUpdate | 更新组件完成 | 发送网络请求;DOM操作;注意: 如果要执行 setState(), 必须有结束条件 |
componentDidUpdate (preProps) {
console.log('执行了 componentDidUpdate 函数')
//比较更新前后的props 是否相同,来决定是否重新渲染组件
// console.log('上一次的props:',preProps,'当前的props:',this.props)
if(preProps.count !== this.props.count){
this.setState({})
}
}
如果要调用setState() 更新状态,必须放在一个if 条件中,因为如果直接调用setState() 更新状态,会导致递归更新陷入死递归!!!
- setState 会调用 render 和 componentDidUpdate
- componentDidUpdate 又会再次调用 setState
3、卸载阶段
执行时机:组件从页面中消失
钩子函数 | 触发时机 | 作用 |
---|---|---|
componentWillUnmount | 卸载组件 | 执行清理工作 |
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
constructor () {
super()
this.state = {
count:0
}
//console.log('执行了constructor 函数')
}
handleClick = () => {
// 调用 forceUpdate 方法能够强制更新
// this.forceUpdate()
// 调用 setState 方法更新数据后触发更新
this.setState({
count:this.state.count + 1
})
}
render () {
console.log('执行了 render 函数')
return (
<div>
{
this.state.count > 3?
<p>满满被揍惨了</p>
:<Counter count={this.state.count}/>
}
<button onClick={this.handleClick}>打满满</button>
</div>
)
}
componentDidUpdate (preProps) {
console.log('执行了 componentDidUpdate 函数')
//比较更新前后的props 是否相同,来决定是否重新渲染组件
console.log('上一次的props:',preProps,'当前的props:',this.props)
if(preProps.count !== this.props.count){
this.setState({})
}
}
}
class Counter extends React.Component{
componentDidMount(){
//开启定时器
setInterval(()=>{
console.log('定时器正在执行');
},500)
}
render(){
return <h1 id='title'>统计打满满的次数:{this.props.count}</h1>
}
componentWillUnmount(){
console.log('执行了 componentWillUnmount 函数');
//清理定时器
clearInterval(this.timerId)
}
}
ReactDOM.render(<App />, document.getElementById('root'))
生命周期完整图示: