目录
React组件生命周期
组件的生命周期:组件从被创建到挂载到页面运行,再到组件不用时的卸载过程。其意义在于有助于理解组件的运行方式、完成更复杂的组件功能、分析组件错误的原因等。生命周期的每个阶段总是伴随着一些方法的调用,这些方法就是生命周期的钩子函数,其作用是为开发人员在不同阶段操作组件提供了时机。注意:只有类组件才有生命周期。
React的生命周期分为如下三个阶段,我们要清楚的了解到每个阶段的执行时机,每个阶段钩子函数的执行顺序,以及每个阶段钩子函数的作用。
React v16 开始,对生命周期函数做了一些更改,且分为两个版本:v16.3 及之前的版本,v16.4 及之后的版本,由于现在React已经更新到React18了,再研究React16.3之前的生命周期也没有太大的意义,就以现在如下的生命周期讲解:React 生命周期查看在线地址:查看地址。
看完这篇文章,如果想进一步了解React生命周期,推荐看一下官方文档:官方网址 。
我会在讲完常用的生命周期钩子函数之后会讲解一下不常用的生命周期函数,虽然在项目中使用的不多,但是大家可以简单的知道有这么一个东西,如果能用就更好了。
挂载阶段
其执行顺序如下:
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
constructor(props){
super(props)
console.log('生命周期钩子:constructor')
}
componentDidMount(){
console.log('生命周期钩子:componentDidMount')
}
render() {
console.log('生命周期钩子:render')
return (
<div>
</div>
)
}
}
ReactDOM.render(<App />,document.getElementById('root'))
钩子函数 | 触发时机 | 作用 |
---|---|---|
constructor | 创建组件时,最先执行 | 初始化state、为事件处理程序绑定this |
render | 每次组件渲染都会触发 | 渲染UI( 注意:不能调用setState() ) |
componentDidMount | 组件挂载(完成DOM渲染)后 | 发送网络请求、进行DOM操作 |
更新阶段
其执行顺序如下:
render()阶段:导致更新的三种执行时机:setState()、组件受到新的props、forceUpdate()。任何一种变化都会导致组件的重新渲染。
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
state = {
count:0
}
addCount = () =>{
this.setState({
count:this.state.count+1
})
}
render() {
console.log('生命周期钩子:render')
return (
<div>
{/* 向子组件传递count属性 */}
<Count count={this.state.count} />
<button onClick={this.addCount}>点击+1</button>
</div>
)
}
}
// 定义子组件
class Count extends React.Component {
render(){
console.log('----子组件----生命周期钩子:render')
// 子组件通过props接收父组件传递过来的count值
return <h1>计数器:{this.props.count}</h1>
}
}
ReactDOM.render(<App />,document.getElementById('root'))
每次更新state里面的数据会触发一次更新,每次向子组件传递props数据会触发一次更新。
将点击事件设置为强制更新时不会变化页面数据,也会触发更新,而且是父子组件的同时更新。
componentDidUpdate()阶段:
我们在定义完子组件时,通过执行componentDidUpdate来监视更新完后的变化。
钩子函数 | 触发时机 | 作用 |
---|---|---|
render | 每次组件渲染完都会触发 | 渲染UI(与挂载阶段是同一个render) |
componentDidUpdate |
组件更新(完成DOM渲染)后 | 发送网络请求、DOM操作 |
注意:componentDidUpdate如果要setState()必须放在一个if条件中。
卸载阶段
卸载阶段的钩子函数只有一个,没有执行顺序,其执行时机:组件从页面上消失。
钩子函数 | 触发时机 | 作用 |
---|---|---|
componentWillUnmount |
组件卸载(从页面上消失) | 执行清理工作(比如:清理定时器等) |
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
state = {
count:0
}
addCount = () =>{
this.setState({
count:this.state.count+1
})
}
render() {
return (
<div>
{
this.state.count > 3 ?(
<p>事不过三,你过了!!!</p>
) : (
<Count count={this.state.count} />
)
}
<button onClick={this.addCount}>点击+1</button>
</div>
)
}
}
// 定义子组件
class Count extends React.Component {
render(){
return <h1>计数器:{this.props.count}</h1>
}
// 卸载阶段钩子函数
componentWillUnmount(){
console.log('生命周期钩子函数:componentWillUnmount')
}
}
ReactDOM.render(<App />,document.getElementById('root'))
那么如何执行清理工作呢?如下举一个简单的定时器的例子:
不常用的生命周期钩子函数(了解)
看过上文的小伙伴看到如下的图片会立马知道,出现了三个上文没有出现的生命周期钩子,因为在项目中使用的频率较少,上文就省略了,接下来会单独为这三个钩子进行讲解,大家可以做一个了解,如果能够使用那最好不过了。详情请看官方文档:官方文档 。
static getDerivedStateFromProps:
作用是:state 的值在任何时候都取决于 props ,只要该函数return返回的是state里面的某个属性,页面的该state属性所渲染的值,就以该函数return的值为主,页面该属性的值状态不再发生更新。
什么意思呢?别急,我们先看一下,这个生命周期钩子的执行顺序是否与生命周期图相同,如下:
接下来我传入props的为state属性中的count并设置为10,如下代码:
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
constructor(props){
console.log('---constructor')
super(props)
// 初始化状态
this.state = {count:0,num:1}
}
// 子组件+1操作
addCount = () =>{
this.setState({
count:this.state.count+1
})
}
// 子=父组件+1操作
addNum = () =>{
this.setState({
num:this.state.num+1
})
}
static getDerivedStateFromProps(props,state){
console.log('-----getDerivedStateFromProps',props,state)
// 必须返回状态对象或null
return props
}
componentDidMount(){
console.log('---componentDidMount')
}
render() {
console.log('---render')
return (
<div>
<Count count={this.state.count} />
<h1>父组件本身的数值:{this.state.num}</h1>
<button onClick={this.addCount}>点击计数器+1</button>
<button onClick={this.addNum}>点击父组件本身的数值+1</button>
</div>
)
}
}
// 定义子组件
class Count extends React.Component {
render(){
return <h1>计数器:{this.props.count}</h1>
}
}
ReactDOM.render(<App count={10} />,document.getElementById('root'))
官方文档明确指出,如下观点:
shouldComponentUpdate:
作用是:判断组件是否应该被更新,如果这个钩子不写,它有个默认的返回值,永远返回为真。如果你返回了false,不好意思,这个钩子函数以下的所以钩子函数都不能在调用,类似有个阀门。
getSnapshotBeforeUpdate:
最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息例如滚动位置。此生命周期方法的任何返回值将作为参数传递给componentDidUpdate()。
读了这个官方的解释,大家可能会觉得有点懵,什么意思呢?举个例子:大家可能喜欢去一些旅游景点照相,你照相前摄影师会提醒你,要想好摆好什么pose,一点相机按下拍照,拍出的照片里面的内容就不能再反悔了,所以这个钩子函数里面的Snapshot就是在更新结束前的得到快照,可以将返回值传递给更新后的钩子函数。如下代码解释:
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
constructor(props){
console.log('---constructor')
super(props)
// 初始化状态
this.state = {count:0,num:1}
}
// 子组件+1操作
addCount = () =>{
this.setState({
count:this.state.count+1
})
}
// 子=父组件+1操作
addNum = () =>{
this.setState({
num:this.state.num+1
})
}
componentDidMount(){
console.log('---componentDidMount')
}
// 在更新前获取快照
getSnapshotBeforeUpdate(){
console.log('-----getSnapshotBeforeUpdate')
// 将返回值传递给更新完毕的钩子,可以是任意值
return 'pose摆好了,就等你拍了'
}
// 组件更新完毕,能接收三个参数:更新前的props,更新前的state,以及快照函数的返回值
componentDidUpdate(preProps,preState,snapshotValue){
console.log('-----componentDidUpdate',preProps,preState,snapshotValue+'好了,我已经拍完了')
}
render() {
console.log('---render')
return (
<div>
<Count count={this.state.count} />
<h1>父组件本身的数值:{this.state.num}</h1>
<button onClick={this.addCount}>点击计数器+1</button>
<button onClick={this.addNum}>点击父组件本身的数值+1</button>
</div>
)
}
}
// 定义子组件
class Count extends React.Component {
render(){
return <h1>计数器:{this.props.count}</h1>
}
}
ReactDOM.render(<App count={10} />,document.getElementById('root'))
此生命周期钩子也不常见,官方已经明确说明了,这里不在赘述:
总结:(标黄:仅作了解即可)
1)初始化阶段:由ReactDOM.render()触发——初次渲染
1、constructor()
2、static getDerivedStateFromProps(props,state)
3、render()
4、componentDidMount()
2)更新阶段:由组件内部的this.setState()或父组件重新render()触发
1、static getDerivedStateFromProps(props,state)
2、shouldComponentUpdate()
3、render()
4、getSnapshotBeforeUpdate()
5、componentDidUpdate()
3)卸载组件:由ReactDOM.unmountComponentAtNode()触发
1、componentWillUnmount()
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/139994.html