React组件在其应用生命周期中会经历不同的阶段,尽管幕后发生的事情可能并不明显。
这些阶段包括:
- 挂载
- 更新
- 卸载
- 错误处理
每个阶段都有相应的方法,可以在该阶段对组件执行特定操作。例如,当从网络获取数据时,您可能希望在componentDidMount()
方法(在挂载阶段可用)中调用处理API调用的函数。
了解不同的生命周期方法对于React应用程序的开发至关重要,因为它允许我们在需要时精确地触发操作,而不会与其他操作混淆。本文将介绍每个生命周期,包括可用的方法以及我们使用它们的场景类型。
挂载阶段
将挂载视为组件生命周期的初始阶段。在挂载发生之前,组件尚未存在——它只是DOM中的一闪而过,直到挂载发生并将其作为文档的一部分连接起来。
一旦组件挂载,我们就可以利用许多方法:constructor()
、render()
、componentDidMount()
和static getDerivedStateFromProps()
。每个方法都有其自身的用途,让我们按顺序来看一下。
constructor()
当直接在组件上设置状态以将方法绑定在一起时,需要constructor()
方法。它看起来像这样:
// 一旦输入组件开始挂载... constructor(props) { // ...设置一些props... super(props); // ...在这种情况下,是一个空白用户名... this.state = { username: '' }; // ...然后绑定一个处理输入更改的方法 this.handleInputChange = this.handleInputChange.bind(this); }
重要的是要知道,constructor
是创建组件时调用的第一个方法。组件尚未渲染(即将到来),但DOM已经知道它,我们可以在它渲染之前与它挂钩。因此,这不是我们调用setState()
或引入任何副作用的地方,因为组件仍然处于构建阶段!
我之前写过一篇关于refs的教程,我注意到的一件事是在使用React.createRef()
时,可以在constructor
中设置ref。这是合理的,因为refs用于更改值而无需props或必须使用更新值重新渲染组件:
constructor(props) { super(props); this.state = { username: '' }; this.inputText = React.createRef(); }
render()
render()
方法是组件的标记在前端显示的地方。用户此时可以看到并访问它。如果您曾经创建过React组件,那么您已经熟悉它了——即使您没有意识到——因为它需要输出标记。
class App extends React.Component { // 挂载过程中,请渲染以下内容! render() { return ( <div> <p>Hello World!</p> </div> ) } }
但这并不是render()
的全部用途!它还可以用于渲染组件数组:
class App extends React.Component { render () { return [ <h2 id="JavaScript-Tools">JavaScript Tools</h2>, <frontend></frontend>, <backend></backend> ] } }
甚至组件片段:
class App extends React.Component { render() { return ( <react.fragment><p>Hello World!</p></react.fragment> ) } }
我们还可以使用它来渲染DOM层次结构之外的组件(类似于React Portal):
// 我们正在创建一个门户,允许组件在DOM中移动 class Portal extends React.Component { // 首先,我们创建一个div元素 constructor() { super(); this.el = document.createElement("div"); } // 挂载后,让我们追加组件的子元素 componentDidMount = () => { portalRoot.appendChild(this.el); }; // 如果组件从DOM中移除,那么我们也将其子元素移除 componentWillUnmount = () => { portalRoot.removeChild(this.el); }; // 啊,现在我们可以根据需要渲染组件及其子元素 render() { const { children } = this.props; return ReactDOM.createPortal(children, this.el); } }
当然,render()
可以渲染数字和字符串……
class App extends React.Component { render () { return "Hello World!" } }
以及null或布尔值:
class App extends React.Component { render () { return null } }
componentDidMount()
componentDidMount()
这个名字是否说明了它的含义?此方法在组件挂载(即连接到DOM)后调用。在我撰写的另一篇关于在React中获取数据的教程中,这就是您要向API发出请求以获取数据的地方。
我们可以使用您的fetch方法:
fetchUsers() { fetch(`https://jsonplaceholder.typicode.com/users`) .then(response => response.json()) .then(data => this.setState({ users: data, isLoading: false, }) ) .catch(error => this.setState({ error, isLoading: false })); }
然后在componentDidMount()
钩子中调用该方法:
componentDidMount() { this.fetchUsers(); }
我们还可以添加事件监听器:
componentDidMount() { el.addEventListener() }
很简洁,对吧?
static getDerivedStateFromProps()
这是一个有点冗长的名字,但static getDerivedStateFromProps()
并不像听起来那么复杂。它在挂载阶段的render()
方法之前以及更新阶段之前调用。它返回一个对象来更新组件的状态,或者在没有要更新的内容时返回null
。
为了理解它的工作原理,让我们实现一个计数器组件,它将为其计数器状态设置一个特定值。只有当maxCount
的值更高时,此状态才会更新。maxCount
将从父组件传递。
这是父组件:
class App extends React.Component { constructor(props) { super(props) this.textInput = React.createRef(); this.state = { value: 0 } } handleIncrement = e => { e.preventDefault(); this.setState({ value: this.state.value 1 }) }; handleDecrement = e => { e.preventDefault(); this.setState({ value: this.state.value - 1 }) }; render() { return ( <react.fragment><p>Max count: { this.state.value }</p> - <counter maxcount="{this.state.value}"></counter></react.fragment> ) } }
我们有一个按钮用于增加maxCount
的值,我们将其传递给Counter
组件。
class Counter extends React.Component { state={ counter: 5 } static getDerivedStateFromProps(nextProps, prevState) { if (prevState.counter <p>Count: {this.state.counter}</p> ) } }
在Counter
组件中,我们检查counter
是否小于maxCount
。如果是,我们将counter
设置为maxCount
的值。否则,我们什么也不做。
更新阶段
当组件的props或状态更改时,会发生更新阶段。与挂载一样,更新也有自己的一组可用方法,我们接下来将介绍。也就是说,值得注意的是,render()
和getDerivedStateFromProps()
也会在此阶段触发。
shouldComponentUpdate()
当组件的状态或props更改时,我们可以使用shouldComponentUpdate()
方法来控制组件是否应该更新。此方法在渲染发生之前以及接收状态和props时调用。默认行为为true
。要每次状态或props更改时都重新渲染,我们会这样做:
shouldComponentUpdate(nextProps, nextState) { return this.state.value !== nextState.value; }
当返回false
时,组件不会更新,而是调用render()
方法来显示组件。
getSnapshotBeforeUpdate()
我们可以做的一件事是在某个时间点捕获组件的状态,这就是getSnapshotBeforeUpdate()
的设计目的。它在render()
之后但提交任何新更改到DOM之前调用。返回值作为第三个参数传递给componentDidUpdate()
。
它将先前状态和props作为参数:
getSnapshotBeforeUpdate(prevProps, prevState) { // ... }
在我看来,此方法的用例很少。它是一种您可能不会经常使用到的生命周期方法。
componentDidUpdate()
将componentDidUpdate()
添加到方法列表中,其中名称大致说明了所有内容。如果组件更新,那么我们可以使用此方法在此时与它挂钩,并将其传递给组件的先前props和状态。
componentDidUpdate(prevProps, prevState) { if (prevState.counter !== this.state.counter) { // ... } }
如果您曾经使用过getSnapshotBeforeUpdate()
,您还可以将返回值作为参数传递给componentDidUpdate()
:
componentDidUpdate(prevProps, prevState, snapshot) { if (prevState.counter !== this.state.counter) { // .... } }
卸载阶段
我们在这里几乎看到了挂载阶段的反面。正如您可能预期的那样,卸载发生在组件从DOM中清除并且不再可用时。
我们这里只有一个方法:componentWillUnmount()
这在组件卸载和销毁之前调用。这就是我们想要在组件离开后执行任何必要的清理的地方,例如删除可能在componentDidMount()
中添加的事件监听器,或清除订阅。
// 删除事件监听器 componentWillUnmount() { el.removeEventListener() }
错误处理阶段
组件中可能会出现问题,这可能会导致错误。我们已经有一段时间使用错误边界来帮助解决这个问题。此错误边界组件使用一些方法来帮助我们处理可能遇到的错误。
getDerivedStateFromError()
我们使用getDerivedStateFromError()
来捕获从子组件抛出的任何错误,然后我们使用它来更新组件的状态。
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } render() { if (this.state.hasError) { return ( <h1 id="Oops-something-went-wrong">Oops, something went wrong :(</h1> ); } return this.props.children; } }
在此示例中,当从子组件抛出错误时,ErrorBoundary
组件将显示“哎呀,出现了一些问题”。
componentDidCatch()
虽然getDerivedStateFromError()
适用于在发生副作用(如错误日志记录)的情况下更新组件的状态,但我们应该使用componentDidCatch()
,因为它在提交阶段调用,此时DOM已更新。
componentDidCatch(error, info) { // 将错误记录到服务 }
getDerivedStateFromError()
和componentDidCatch()
都可以在ErrorBoundary
组件中使用:
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, info) { // 将错误记录到服务 } render() { if (this.state.hasError) { return ( <h1 id="Oops-something-went-wrong">Oops, something went wrong :(</h1> ); } return this.props.children; } }
这就是React组件的生命周期!
了解React组件如何与DOM交互是一件很酷的事情。很容易认为会发生一些“魔法”,然后页面上就会出现一些东西。但是React组件的生命周期表明,这种疯狂是有秩序的,它旨在赋予我们很大的控制权,以便从组件到达DOM到它消失的时间发生的事情。
我们在相对较短的空间内涵盖了很多内容,但希望这能让您很好地了解React如何处理组件,以及我们在处理的各个阶段拥有什么样的能力。如果您对这里介绍的任何内容不清楚,请随时提出任何问题,我很乐意尽力提供帮助!
以上是反应生命周期的圆的详细内容。更多信息请关注PHP中文网其他相关文章!

具有CSS的自定义光标很棒,但是我们可以将JavaScript提升到一个新的水平。使用JavaScript,我们可以在光标状态之间过渡,将动态文本放置在光标中,应用复杂的动画并应用过滤器。

互动CSS动画和元素相互启动的元素在2025年似乎更合理。虽然不需要在CSS中实施乒乓球,但CSS的灵活性和力量的增加,可以怀疑Lee&Aver Lee&Aver Lee有一天将是一场

有关利用CSS背景滤波器属性来样式用户界面的提示和技巧。您将学习如何在多个元素之间进行背景过滤器,并将它们与其他CSS图形效果集成在一起以创建精心设计的设计。

好吧,事实证明,SVG的内置动画功能从未按计划进行弃用。当然,CSS和JavaScript具有承载负载的能力,但是很高兴知道Smil并没有像以前那样死在水中

是的,让#039;跳上文字包装:Safari Technology Preview In Pretty Landing!但是请注意,它与在铬浏览器中的工作方式不同。

此CSS-tricks更新了,重点介绍了年鉴,最近的播客出现,新的CSS计数器指南以及增加了几位新作者,这些新作者贡献了有价值的内容。

在大多数情况下,人们展示了@Apply的@Apply功能,其中包括Tailwind的单个property实用程序之一(会改变单个CSS声明)。当以这种方式展示时,@Apply听起来似乎很有希望。如此明显


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

Atom编辑器mac版下载
最流行的的开源编辑器

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

禅工作室 13.0.1
功能强大的PHP集成开发环境

WebStorm Mac版
好用的JavaScript开发工具