"小和山的菜鸟们",为前端开发者提供技术相关资讯以及系列基础文章。为更好的用户体验,请您移至我们官网小和山的菜鸟们 ( 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()
方法是 class
组件中唯一必须实现的方法。
当 render
被调用时,它会检查 this.props
和 this.state
的变化并返回以下类型之一:
JSX
创建。render
方法可以返回多个元素。DOM
子树中。DOM
中会被渲染为文本节点null
。什么都不渲染。render()
函数应该为纯函数,这意味着在不修改组件 state
的情况下,每次调用时都返回相同的结果,并且它不会直接与浏览器交互。
如需与浏览器进行交互,请在 componentDidMount()
或其他生命周期方法中执行你的操作。保持 render()
为纯函数,可以使组件更容易思考。
注意: 如果shouldComponentUpdate()
返回false
,则不会调用render()
。
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()
会在组件挂载后(插入 DOM 树中)立即调用。
componentDidMount
中通常进行哪里操作呢?
DOM
的操作可以在这里进行;componentWillUnmount
取消订阅);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()
会在组件卸载及销毁之前直接调用。
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(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 更改时重新渲染。
static getDerivedStateFromProps(props, state)
getDerivedStateFromProps
会在调用 render
方法之前调用,并且在初始挂载及后续更新时都会被调用。
state
,如果返回 null
则不更新任何内容。getDerivedStateFromProps
的存在只有一个目的:让组件在 props 变化时更新 state
,即 state
的值在任何时候都取决于 props
。注意: 不管原因是什么,都会在每次渲染前触发此方法。
getSnapshotBeforeUpdate(prevProps, prevState)
在 React
更新 DOM
之前回调的一个函数,可以获取 DOM
更新前的一些信息(比如说滚动位置);
componentDidUpdate()
。UI
处理中,如需要以特殊方式处理滚动位置的聊天线程等。snapshot
的值(或 null
)。另外,React
中还提供了一些过期的生命周期函数,这些函数已经不推荐使用。
更详细的生命周期相关的内容,可以参考React 官网
互联网时代,人们渐渐对 域名 有了越来越多的关注,一个好域名带给企业的将是长...
简介: 背景自从五十年前关系型数据模型被发明出来后,凭借优秀的表达能力和清晰...
前几天,同事接到一个积分商城项目,其中有一个卡券兑换礼品功能。我想了一会没...
坐标成都,大专,4年前端,分享一次自己在蚂蚁金服的面试经历。 一面 1.自我介绍...
前言:eslint我们常应用在代码静态扫描中,通过设定的eslint的语法规则,来对代...
表现 例如: HTML: div class=first div class=first-child1first-child1/div d...
本文学习的内容主要如下所示: 1.浏览器支持 2.图片 3.响应式工具 4.遇到的问题 ...
文字链接是网页中最常见的页面元素,在默认状态下,文字链接样式都是带下划线的...
html结构 body div class=wrapper div class=left/div div class=right/div /div...
前言 在上一篇中我们把图通过邻接表数组表示出来了,这个数据结构将会做我们实现...