更多react知识: React专栏
组件生命周期(★★★)
目标
-
说出组件生命周期对应的钩子函数
-
钩子函数调用的时机
概述
意义:组件的生命周期有助于理解组件的运行方式,完成更复杂的组件功能、分析组件错误原因等
组件的生命周期: 组件从被创建到挂载到页面中运行,再到组件不在时卸载的过程
生命周期的每个阶段总是伴随着一些方法调用,这些方法就是生命周期的钩子函数
构造函数的作用:为开发人员在不同阶段操作组件提供了实际
生命周期阶段
创建时(挂载阶段)
-
执行时机:组件创建时(页面加载时)
-
执行顺序
componentDidMount函数内发送请求
class App extends React.Component {
constructor(props) {
super(props)
// 初始化state
this.state = {
count: 0
}
console.warn('生命周期钩子函数: constructor')
}
// 1 进行DOM操作
// 2 发送ajax请求,获取远程数据
componentDidMount() {
// axios.get('http://api.....')
// const title = document.getElementById('title')
// console.log(title)
console.warn('生命周期钩子函数: componentDidMount')
}
render() {
// 错误演示!!! 不要在render中调用setState()
// this.setState({
// count: 1
// })
console.warn('生命周期钩子函数: render')
return (
<div>
<h1 id="title">统计豆豆被打的次数:</h1>
<button id="btn">打豆豆</button>
</div>
)
}
}
更新时
执行时机:setState()、 forceUpdate()、 组件接收到新的props
说明:以上三者任意一种变化,组件就会重新渲染
执行顺序:
class App extends React.Component {
constructor(props) {
super(props)
// 初始化state
this.state = {
count: 0
}
}
// 打豆豆
handleClick = () => {
// this.setState({
// count: this.state.count + 1
// })
// 演示强制更新:
this.forceUpdate()
}
render() {
console.warn('生命周期钩子函数: 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>统计豆豆被打的次数:{this.props.count}</h1>
}
}
class App extends React.Component {
constructor(props) {
super(props)
// 初始化state
this.state = {
count: 0
}
}
// 打豆豆
handleClick = () => {
this.setState({
count: this.state.count + 1
})
}
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 条件中
// 因为:如果直接调用 setState() 更新状态,也会导致递归更新!!!
componentDidUpdate(prevProps) {
console.warn('--子组件--生命周期钩子函数: componentDidUpdate')
// 正确做法:
// 做法:比较更新前后的props是否相同,来决定是否重新渲染组件
console.log('上一次的props:', prevProps, ', 当前的props:', this.props)
if (prevProps.count !== this.props.count) {
// this.setState({})
// 发送ajax请求的代码
}
// 错误演示!!!
// this.setState({})
// 获取DOM
// const title = document.getElementById('title')
// console.log(title.innerHTML)
}
}
卸载时
执行时机:组件从页面中消失
作用:用来做清理操作
class App extends React.Component {
constructor(props) {
super(props)
// 初始化state
this.state = {
count: 0
}
}
// 打豆豆
handleClick = () => {
this.setState({
count: this.state.count + 1
})
}
render() {
return (
<div>
{this.state.count > 3 ? (
<p>豆豆被打死了~</p>
) : (
<Counter count={this.state.count} />
)}
<button onClick={this.handleClick}>打豆豆</button>
</div>
)
}
}
class Counter extends React.Component {
componentDidMount() {
// 开启定时器
this.timerId = setInterval(() => {
console.log('定时器正在执行~')
}, 500)
}
render() {
return <h1>统计豆豆被打的次数:{this.props.count}</h1>
}
componentWillUnmount() {
console.warn('生命周期钩子函数: componentWillUnmount')
// 清理定时器,若不清理,不管调不调用子组件定时器一直执行
clearInterval(this.timerId)
}
}
不常用的钩子函数
旧版的生命周期钩子函数
新版完整生命会走棋钩子函数
getDerivedStateFromProps()
-
getDerivedStateFromProps
会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容 -
不管原因是什么,都会在每次渲染前触发此方法
shouldComponentUpdate()
-
根据
shouldComponentUpdate()
的返回值,判断 React 组件的输出是否受当前 state 或 props 更改的影响。默认行为是 state 每次发生变化组件都会重新渲染 -
当 props 或 state 发生变化时,
shouldComponentUpdate()
会在渲染执行之前被调用。返回值默认为 true
getSnapshotBeforeUpdate()
-
getSnapshotBeforeUpdate()
在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给componentDidUpdate()
-
此用法并不常见,但它可能出现在 UI 处理中,如需要以特殊方式处理滚动位置的聊天线程等