- 生命周期: 组件从创建到加载运行再到卸载的整个过程就是生命周期 (创建 --> 加载运行 --> 卸载)
- 掌握组件生命周期有助于我们理解组件的运行方式,完成更复杂的功能,分析解决错误
- 生命周期的每个阶段中,都有钩子函数,钩子函数能够实现更多的功能
- 只有类组件才有生命周期
1.创建阶段
创建时会顺序执行三个函数: constructor
—> render
—> componentDidMount
import React from 'react'
import ReactDOM from 'react-dom'
class Hello extends React.Component {
constructor () {
super()
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.querySelector('#app'))
执行效果:
钩子函数 | 触发时机 | 作用 |
---|---|---|
constructor | 创建组件时 | 初始化 state;使用 bind 修改方法的this指向 |
render | 每次渲染组件时 | 渲染页面 (不能调用 setState 方法) |
componentDidMount | 渲染完成后 | 发送网络请求;DOM操作 |
2.更新阶段
- 更新时会顺序执行两个函数: render —> componentDidUpdate
- 有三种情况会更新组件:
- forceUpdate(): 调用 forceUpdate() 强制进行更新
- setState(): 调用了setState 方法更新数据
- new props: props 的值发生改变时
-
调用 forceUpdate() 强制进行更新
-
调用了setState 方法更新数据
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
constructor () {
super()
this.state = {
name: '安琪拉',
level: 1,
hp: 680,
mp: 320
}
console.log('执行了constructor 函数')
}
handleClick = () => {
// 调用 forceUpdate 方法能够强制更新
// this.forceUpdate()
// 调用 setState 方法更新数据后触发更新
this.setState({
level: this.state.level + 1,
hp: this.state.hp + 1,
mp: this.state.mp + 1
})
}
render () {
console.log('执行了 render 函数')
return (
<div>
<ul>
<li>英雄: {
this.state.name}</li>
<li>等级: {
this.state.level}</li>
<li>血量: {
this.state.mp}</li>
<li>蓝量: {
this.state.hp}</li>
</ul>
<button onClick={
this.handleClick}>升级</button>
</div>
)
}
componentDidMount () {
console.log('执行了 componentDidMount 函数')
}
componentDidUpdate () {
console.log('执行了 componentDidUpdate 函数')
}
}
ReactDOM.render(<App />, document.querySelector('#app'))
- props的值发生改变时 (更新父组件的state就是更新子组件的props)
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
constructor () {
super()
this.state = {
name: '安琪拉',
level: 1,
hp: 680,
mp: 320
}
console.log('App-constructor')
}
handleClick = () => {
// 调用 forceUpdate 方法能够强制更新
// this.forceUpdate()
// 调用 setState 方法更新数据后出发更新
this.setState({
level: this.state.level + 1,
hp: this.state.hp + 1,
mp: this.state.mp + 1
})
}
render () {
console.log('App-render')
return (
<div>
<Hero attr={
this.state} />
<button onClick={
this.handleClick}>升级</button>
</div>
)
}
componentDidMount () {
console.log('App-componentDidMount')
}
componentDidUpdate () {
console.log('App-componentDidUpdate')
}
}
class Hero extends React.Component {
constructor () {
super()
console.log('Hero-constructor')
}
render () {
console.log('Hero-render')
return (
<ul>
<li>英雄: {
this.props.attr.name}</li>
<li>等级: {
this.props.attr.level}</li>
<li>血量: {
this.props.attr.mp}</li>
<li>蓝量: {
this.props.attr.hp}</li>
</ul>
)
}
componentDidMount () {
console.log('Hero-componentDidMount')
}
componentDidUpdate () {
console.log('Hero-componentDidUpdate')
}
}
ReactDOM.render(<App />, document.querySelector('#app'))
钩子函数 | 触发时机 | 作用 |
---|---|---|
render | 每次渲染 | 渲染页面 |
componentDidUpdate | 更新组件完成 | 发送网络请求;DOM操作;注意: 如果要执行 setState(), 必须有结束条件 |
componentDidUpdate () {
console.log('执行了 componentDidUpdate 函数')
if (this.state.id === 10) {
return
}
this.setState({
id: 10
})
}
如果没有if判断,则会陷入死递归中
- setState 会调用 render 和 componentDidUpdate
- componentDidUpdate 又会再次调用 setState
3.卸载阶段
钩子函数 | 触发时机 | 作用 |
---|---|---|
componentWillUnmount | 卸载组件 | 执行清理工作 |
import React from 'react'
import ReactDOM from 'react-dom'
// 目标: 点击按钮删除 Show 组件
class App extends React.Component {
state = {
flag: true
}
removeDOM = () => {
this.setState({
flag: false
})
}
render () {
return (
<div>
{
this.state.flag ? <Show /> : <div>show被删除了</div>
}
<button onClick={
this.removeDOM}>删除</button>
</div>
)
}
}
class Show extends React.Component {
constructor () {
super()
this.timerId = setInterval(function () {
console.log(123)
}, 500)
}
render () {
return (
<div>Show 组件</div>
)
}
componentWillUnmount = () => {
console.log('Show-componentWillUnmount')
clearInterval(this.timerId)
}
}
ReactDOM.render(<App />, document.querySelector('#app'))