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中文网其他相关文章!

@keyframesandCSSTransitionsdifferincomplexity:@keyframesallowsfordetailedanimationsequences,whileCSSTransitionshandlesimplestatechanges.UseCSSTransitionsforhovereffectslikebuttoncolorchanges,and@keyframesforintricateanimationslikerotatingspinners.

我知道,我知道:有大量的内容管理系统选项可用,而我进行了几个测试,但实际上没有一个是一个,y&#039;知道吗?怪异的定价模型,艰难的自定义,有些甚至最终成为整个&

链接CSS文件到HTML可以通过在HTML的部分使用元素实现。1)使用标签链接本地CSS文件。2)多个CSS文件可通过添加多个标签实现。3)外部CSS文件使用绝对URL链接,如。4)确保正确使用文件路径和CSS文件加载顺序,优化性能可使用CSS预处理器合并文件。

选择Flexbox还是Grid取决于布局需求:1)Flexbox适用于一维布局,如导航栏;2)Grid适合二维布局,如杂志式布局。两者在项目中可结合使用,提升布局效果。

包含CSS文件的最佳方法是使用标签在HTML的部分引入外部CSS文件。1.使用标签引入外部CSS文件,如。2.对于小型调整,可以使用内联CSS,但应谨慎使用。3.大型项目可使用CSS预处理器如Sass或Less,通过@import导入其他CSS文件。4.为了性能,应合并CSS文件并使用CDN,同时使用工具如CSSNano进行压缩。

是的,youshouldlearnbothflexboxandgrid.1)flexboxisidealforone-demensional,flexiblelayoutslikenavigationmenus.2)gridexcelstcelsintwo-dimensional,confffferDesignssignssuchasmagagazineLayouts.3)blosebothenHancesSunHanceSlineHancesLayOutflexibilitibilitibilitibilitibilityAnderibilitibilityAndresponScormentilial anderingStruction

重构自己的代码看起来是什么样的?约翰·瑞亚(John Rhea)挑选了他写的一个旧的CSS动画,并介绍了优化它的思维过程。


热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

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

热门文章

热工具

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

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

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境