快来退出咱们吧!
“ 小和山的菜鸟们 ”,为前端开发者提供技术相干资讯以及系列根底文章。为更好的用户体验,请您移至咱们官网小和山的菜鸟们 (https://xhs-rookies.com/) 进行学习,及时获取最新文章。
“Code tailor”,如果您对咱们文章感兴趣、或是想提一些倡议,微信关注 “小和山的菜鸟们” 公众号,与咱们取的分割,您也能够在微信上观看咱们的文章。每一个倡议或是同意都是对咱们极大的激励!
前言
这节咱们将介绍 React
中组件的生命周期,以及和生命周期互相关联的申明周期函数。
留神:本文所介绍的生命周期为 React 17.0.1 版本,读者期间兴许会有改变,最终生命周期等办法和过程请以官网为主,react 官网
本文会向你介绍以下内容:
- 意识生命周期
- 生命周期解析
- 罕用生命周期函数
- 不罕用生命周期
意识生命周期
很多的事物都有从创立到销毁的整个过程,这个过程称之为是 生命周期;
React
组件也有本人的生命周期,理解组件的生命周期能够让咱们在最合适的中央实现本人想要的性能;
在组件通过不同的生命周期,就会有不同的生命周期函数被触发,让咱们在最合适的中央写入逻辑。
例如:
有一个组件,在生成的时候须要调用网络申请数据,那么就应该在 componentDidMount()
办法中去申请网络。
留神: 咱们谈
React
生命周期时,次要谈的类的生命周期,因为函数式组件是没有生命周期函数的;
生命周期解析
每个类组件都蕴含“生命周期办法”,你能够重写这些办法,以便于在运行过程中特定的阶段执行这些办法,咱们来学习一下这些的生命周期函数,上面是官网给出的生命周期图谱:
挂载时:
- 当咱们挂载一个组件时,会先执行
constructor
构造方法来创立组件; - 而后会调用
getDerivedStateFromProps
,它应返回一个对象来更新state
,如果返回null
则不更新任何内容。 - 紧接着调用
render
函数,获取要渲染的DOM
构造(jsx
),并且开始渲染DOM
; - 当组件挂载胜利(
DOM
渲染实现),会执行componentDidMount
生命周期函数;
更新时:
- 当咱们通过批改
props
,或者调用setState
批改外部状态,或者间接调用forceUpdate
时会从新调用render
函数,进行更新操作; - 当组件的
props
或state
发生变化时会触发更新。此时会调用getDerivedStateFromProps
,它应返回一个对象来更新state
,如果返回null
则不更新任何内容。 - 而后会调用
shouldComponentUpdate
,并依据此函数的返回值,判断 React 组件的输入是否受以后 state 或 props 更改的影响。 - 紧接着会调用
render
函数,随即调用getSnapshotBeforeUpdate
,进行更新操作 - 当更新实现时,会回调
componentDidUpdate
生命周期函数;
卸载时:
- 当咱们的组件不再应用,会被从
DOM
中移除掉(卸载); - 这个时候会回调
componentWillUnmount
生命周期函数;
罕用生命周期函数
render
render()
render()
办法是 class
组件中惟一必须实现的办法。
当 render
被调用时,它会查看 this.props
和 this.state
的变动并返回以下类型之一:
- React 元素。通常通过
JSX
创立。 - 数组或 fragments。使得
render
办法能够返回多个元素。 - Portals。能够渲染子节点到不同的
DOM
子树中。 - 字符串或数值类型。它们在
DOM
中会被渲染为文本节点 - 布尔类型或
null
。什么都不渲染。
render()
函数应该为纯函数,这意味着在不批改组件 state
的状况下,每次调用时都返回雷同的后果,并且它不会间接与浏览器交互。
如需与浏览器进行交互,请在 componentDidMount()
或其余生命周期办法中执行你的操作。放弃 render()
为纯函数,能够使组件更容易思考。
留神: 如果
shouldComponentUpdate()
返回false
,则不会调用render()
。
constructor
constructor(props)
如果不初始化 state
或不进行办法绑定,则不须要为 React
组件实现构造函数。
constructor
中通常只做两件事件:
- 通过给
this.state
赋值对象来初始化外部的state
; - 为事件绑定实例(
this
);
constructor(props) {super(props);
// 不要在这里调用 this.setState()
this.state = {counter: 0};
this.handleClick = this.handleClick.bind(this);
}
只能在构造函数中间接为 this.state
赋值。如需在其余办法中赋值,你应应用 this.setState()
代替。
留神: 防止将
props
的值赋值给state
!这是一个常见的谬误
componentDidMount
componentDidMount()
componentDidMount()
会在组件挂载后(插入 DOM 树中)立刻调用。
componentDidMount
中通常进行哪里操作呢?
- 依赖于
DOM
的操作能够在这里进行; - 在此处发送网络申请就最好的中央;(官网倡议)
- 能够在此处增加一些订阅(会在
componentWillUnmount
勾销订阅);
componentDidUpdate
componentDidUpdate(prevProps, prevState, snapshot)
componentDidUpdate()
会在更新后会被立刻调用,首次渲染不会执行此办法。
- 当组件更新后,能够在此处对
DOM
进行操作; - 如果你对更新前后的
props
进行了比拟,也能够抉择在此处进行网络申请;(例如,当props
未发生变化时,则不会执行网络申请)。
componentDidUpdate(prevProps) {
// 典型用法(不要遗记比拟 props):if (this.props.userID !== prevProps.userID) {this.fetchData(this.props.userID);
}
}
你也能够在 componentDidUpdate()
中 间接调用 setState()
,但请留神 它必须被包裹在一个条件语句里,正如上述的例子那样进行解决,否则会导致死循环。
留神: 如果
shouldComponentUpdate()
返回值为false
,则不会调用componentDidUpdate()
。
componentWillUnmount
componentWillUnmount()
componentWillUnmount()
会在组件卸载及销毁之前间接调用。
- 在此办法中执行必要的清理操作,例如,革除
timer
,勾销网络申请或革除在componentDidMount()
中创立的订阅等; componentWillUnmount()
中 不应调用setState()
,因为该组件将永远不会从新渲染。组件实例卸载后,将永远不会再挂载它。
代码验证上述罕用的生命周期函数:
import React, {Component} from 'react'
class HYTestCpn extends Component {render() {return <h2>HYTestCpn</h2>}
componentWillUnmount() {console.log('HYTestCpn componentWillUnmount')
}
}
export default class App extends Component {constructor(props) {super(props)
this.state = {counter: 0,}
console.log('调用 constructor 办法')
}
render() {console.log('调用 render 办法')
return (
<div>
<h2> 以后计数: {this.state.counter}</h2>
{this.state.counter <= 5 && <HYTestCpn />}
<button onClick={(e) => this.increment()}>+1</button>
</div>
)
}
increment() {
this.setState({counter: this.state.counter + 1,})
}
componentDidMount() {console.log('调用 componentDidMount 办法')
}
componentDidUpdate() {console.log('调用 componentDidUpdate 办法')
}
componentWillUnmount() {console.log('调用 componentWillUnmount 办法')
}
}
不罕用生命周期
除了下面介绍的罕用生命周期函数之外,还有一些不罕用的生命周期函数:
shouldComponentUpdate
shouldComponentUpdate(nextProps, nextState)
当 props
或 state
发生变化时,shouldComponentUpdate()
会在渲染执行之前被调用。返回值默认为 true
。首次渲染或应用 forceUpdate()
时不会调用该办法。
- 依据
shouldComponentUpdate()
的返回值,判断React
组件的输入是否受以后state
或props
更改的影响。 - 默认行为是
state
每次发生变化组件都会从新渲染。大部分状况下,你应该遵循默认行为。 - 此办法仅作为 性能优化的形式 而存在。不要希图依附此办法来“阻止”渲染,因为这可能会产生
bug
。
咱们首先应该思考应用内置的 PureComponent
组件,而不是手动编写,PureComponent
会对 props
和 state
进行浅层比拟,并缩小了跳过必要更新的可能性。
如果须要手动编写,能够将 this.props
与 nextProps
以及 this.state
与 nextState
进行比拟,并返回 false
以告知 React
能够跳过更新。 请留神,返回 false
并不会阻止子组件在 state 更改时从新渲染。
getDerivedStateFromProps
static getDerivedStateFromProps(props, state)
getDerivedStateFromProps
会在调用 render
办法之前调用,并且在初始挂载及后续更新时都会被调用。
- 它应返回一个对象来更新
state
,如果返回null
则不更新任何内容。 getDerivedStateFromProps
的存在只有一个目标:让组件在 props 变动 时更新state
,即state
的值在任何时候都取决于props
。- 此办法无权拜访组件实例。
留神: 不论起因是什么,都会在每次渲染前触发此办法。
getSnapshotBeforeUpdate
getSnapshotBeforeUpdate(prevProps, prevState)
在 React
更新 DOM
之前回调的一个函数,能够获取 DOM
更新前的一些信息(比如说滚动地位);
- 此生命周期的任何返回值将作为参数传递给
componentDidUpdate()
。 - 此用法并不常见,但它可能呈现在
UI
解决中,如须要以非凡形式解决滚动地位的聊天线程等。 - 应返回
snapshot
的值(或null
)。
另外,React
中还提供了一些过期的生命周期函数,这些函数曾经不举荐应用。
更具体的生命周期相干的内容,能够参考 React 官网