【09】基础知识:React组件的生命周期

组件从创建到死亡它会经历一些特定的阶段。

React 组件中包含一系列勾子函数(生命周期回调函数 <=> 生命周期钩子函数 <=> 生命周期函数 <=> 生命周期钩子),会在特定的时刻调用。

我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。

一、react 生命周期旧

在这里插入图片描述

初始化阶段:由 ReactDOM.render() 触发,初次渲染

1、构造器:constructor()

2、组件将要挂载的钩子:componentWillMount()

3、组件渲染或组件更新的钩子:render()

4、 组件挂载完毕的钩子:componentDidMount()

更新阶段:由组件内部 this.setSate() / this.forceUpdate() 或父组件 render 触发

1、控制组件更新的 “阀门” :shouldComponentUpdate()

2、组件将要更新的钩子:componentWillUpdate()

3、组件渲染或组件更新的钩子:render()

4、组件更新完毕的钩子:componentDidUpdate()

卸载组件:由 ReactDOM.unmountComponentAtNode() 触发

1、组件将要卸载的钩子:componentWillUnmount()

父组件 render:组件 props 值改变触发

1、组件将要接收新的 props 的钩子:componentWillReceiveProps()

二、react 生命周期新

在这里插入图片描述
初始化阶段:由 ReactDOM.render() 触发,初次渲染

1、构造器:constructor()

2、从 props 得到一个派生状态:static getDerivedStateFromProps()

3、组件渲染或组件更新的钩子:render()

4、 组件挂载完毕的钩子:componentDidMount()

更新阶段:由组件内部 this.setSate() / this.forceUpdate() 或父组件 render 触发

1、static getDerivedStateFromProps()

2、控制组件更新的 “阀门” :shouldComponentUpdate()

3、组件渲染或组件更新的钩子:render()

4、在更新之前获取快照:getSnapshotBeforeUpdate()

5、组件更新完毕的钩子:componentDidUpdate()

卸载组件:由 ReactDOM.unmountComponentAtNode() 触发

1、组件将要卸载的钩子:componentWillUnmount()

三、新旧生命周期总结

重要的勾子

1、组件渲染或组件更新的钩子:render()

2、组件挂载完毕的钩子:componentDidMount()

一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息

3、组件将要卸载的钩子:componentWillUnmount()

一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

即将废弃的勾子

现在使用会出现警告,下一个大版本需要加上 UNSAFE_ 前缀才能使用,以后可能会被彻底废弃,不建议使用。

1、组件将要挂载的钩子:componentWillMount()

2、组件将要接收新的 props 的钩子:componentWillReceiveProps()

3、组件将要更新的钩子:componentWillUpdate()

四、案例

案例1:引出生命周期

需求:定义组件实现以下功能:

1、让指定的文本做显示 / 隐藏的渐变动画

2、从完全可见,到彻底消失,耗时 2S

3、点击 “不活了” 按钮从界面中卸载组件

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>1_引出生命周期</title>
</head>
<body><!-- 准备好一个“容器” --><div id="test"></div><!-- 引入react核心库 --><script type="text/javascript" src="../js/react.development.js"></script><!-- 引入react-dom,用于支持react操作DOM --><script type="text/javascript" src="../js/react-dom.development.js"></script><!-- 引入babel,用于将jsx转为js --><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/babel">// 创建组件class Life extends React.Component {state = { opacity: 1 }death = () => {// clearInterval(this.timer) // 清除定时器(可以卸载componentWillUnmount中)ReactDOM.unmountComponentAtNode(document.getElementById('test')) // 卸载组件}// 组件挂载完毕的钩子componentDidMount() {console.log('componentDidMount')this.timer = setInterval(() => {let { opacity } = this.state // 获取原状态opacity -= 0.1 // 减小0.1if (opacity <= 0) opacity = 1 this.setState({ opacity }) // 设置新的透明度}, 200)}// 组件将要卸载的钩子componentWillUnmount() {console.log('componentWillUnmount')clearInterval(this.timer) // 清除定时器}// 初始化渲染、状态更新之后 (state变化会触发render函数,定时器如果写在render中,会造成无限递归)render() {console.log('render')return (<div><h2 style={{ opacity: this.state.opacity }}>React学不会怎么办?</h2><button onClick={this.death}>不活了</button></div>)}}// 渲染组件ReactDOM.render(<Life />, document.getElementById('test'))</script>
</body>
</html>

案例二:React 生命周期旧

累加器,点击数值+1

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>2_react生命周期(旧)</title>
</head>
<body><!-- 准备好一个“容器” --><div id="test"></div><!-- 引入react核心库 --><script type="text/javascript" src="../js/react.development.js"></script><!-- 引入react-dom,用于支持react操作DOM --><script type="text/javascript" src="../js/react-dom.development.js"></script><!-- 引入babel,用于将jsx转为js --><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/babel">//  创建组件class Count extends React.Component {// 构造器constructor(props) {console.log('Count---constructor')super(props)this.state = { count: 0 } // 初始化状态}// 加1按钮的回调add = () => {const { count } = this.statethis.setState({ count: count+1 }) // 更新状态}// 卸载组件按钮的回调death = () => {ReactDOM.unmountComponentAtNode(document.getElementById('test'))}// 强制更新按钮的回调force = () => {this.forceUpdate()}// 组件将要挂载的钩子componentWillMount() {console.log('Count---componentWillMount')}// 控制组件更新的 “阀门” shouldComponentUpdate() {console.log('Count---shouldComponentUpdate')// 不写时,默认值为true,代表允许组件更新;写了以后,必须有返回值Boolan,true/falsereturn true}// 组件将要更新的钩子componentWillUpdate() {console.log('Count---componentWillUpdate')}// 组件渲染或组件更新的钩子render() {console.log('Count---render')const { count } = this.statereturn (<div><h2>当前求和为:{ count }</h2><button onClick={this.add}>点我+1</button><button onClick={this.death}>卸载组件</button><button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button></div>)}// 组件挂载完毕的钩子componentDidMount() {console.log('Count---componentDidMount')}// 组件更新完毕的钩子componentDidUpdate() {console.log('Count---componentDidUpdate')}// 组件将要卸载的钩子componentWillUnmount() {console.log('Count---componentWillUnmount')}}// 渲染组件ReactDOM.render(<Count />, document.getElementById('test'))</script>
</body>
</html>

父组件 render 触发子组件 props 值改变

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>2_react生命周期(旧)</title>
</head>
<body><!-- 准备好一个“容器” --><div id="car"></div><!-- 引入react核心库 --><script type="text/javascript" src="../js/react.development.js"></script><!-- 引入react-dom,用于支持react操作DOM --><script type="text/javascript" src="../js/react-dom.development.js"></script><!-- 引入babel,用于将jsx转为js --><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/babel">// 父组件class A extends React.Component {// 初始化状态state = { carName: '奔驰' }changeCar = () => {this.setState({ carName: '奥拓' })}render() {return (<div><div>我是A组件</div><button onClick={this.changeCar}>换车</button><B carName={this.state.carName}/></div>)}}// 子组件class B extends React.Component {// 组件将要接收新的props的钩子(props第一次接收值时不触发)componentWillReceiveProps(props) {console.log('B---componentWillReceiveProps', props)}// 控制组件更新的 “阀门” shouldComponentUpdate() {console.log('B---shouldComponentUpdate')// 不写时,默认值为true,代表允许组件更新;写了以后,必须有返回值Boolan,true/falsereturn true}// 组件将要更新的钩子componentWillUpdate() {console.log('B---componentWillUpdate')}// 组件渲染或组件更新的钩子render() {console.log('B---render')const { carName } = this.propsreturn (<div>我是B组件,接收到的车是:{carName}</div>)}// 组件更新完毕的钩子componentDidUpdate() {console.log('Count---componentDidUpdate')}}// 渲染组件ReactDOM.render(<A />, document.getElementById('car'))</script>
</body>
</html>

案例三:React 生命周期新

新生命周期新增方法:

static getDerivedStateFromProps() 从props得到一个派生状态,此方法适用于罕见的用例,即 state 的值在任何时候都取决于 props 。派生状态会导致代码冗余。

getSnapshotBeforeUpdate() 在更新之前获取快照,此用法并不常见。它使得组件能在发生改变之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>3_react生命周期(新)</title>
</head>
<body><!-- 准备好一个“容器” --><div id="test"></div><!-- 引入react核心库 --><script type="text/javascript" src="../js/17.0.1/react.development.js"></script><!-- 引入react-dom,用于支持react操作DOM --><script type="text/javascript" src="../js/17.0.1/react-dom.development.js"></script><!-- 引入babel,用于将jsx转为js --><script type="text/javascript" src="../js/17.0.1/babel.min.js"></script><script type="text/babel">// 创建组件class Count extends React.Component {// 构造器constructor(props) {console.log('Count---constructor')super(props)this.state = { count: 0 } // 初始化状态}// 加1按钮的回调add = () => {const { count } = this.statethis.setState({ count: count+1 }) // 更新状态}// 卸载组件按钮的回调death = () => {ReactDOM.unmountComponentAtNode(document.getElementById('test'))}// 强制更新按钮的回调force = () => {this.forceUpdate()}// 从props得到一个派生状态:若state的值在任何时候都取决于props,那么可以使用getDerivedStateFromPropsstatic getDerivedStateFromProps(props, state) {console.log('getDerivedStateFromProps', props, state)return null // 必须有返回值,状态对象或者null}// 在更新之前获取快照getSnapshotBeforeUpdate() {console.log('getSnapshotBeforeUpdate')return 'atguigu' // 必有有返回值,快照或者null,将作为参数传递给 componentDidUpdate()}// 控制组件更新的 “阀门” shouldComponentUpdate() {console.log('Count---shouldComponentUpdate')// 不写时,默认值为true,代表允许组件更新;写了以后,必须有返回值Boolan,true/falsereturn true}// 组件渲染或组件更新的钩子render() {console.log('Count---render')const { count } = this.statereturn (<div><h2>当前求和为:{ count }</h2><button onClick={this.add}>点我+1</button><button onClick={this.death}>卸载组件</button><button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button></div>)}// 组件挂载完毕的钩子componentDidMount() {console.log('Count---componentDidMount')}// 组件更新完毕的钩子(接收参数:之前的的props、之前的state、传过来的快照)componentDidUpdate(prevProps, prevState, snapshotValue) {console.log('Count---componentDidUpdate', prevProps, prevState, snapshotValue)}// 组件将要卸载的钩子componentWillUnmount() {console.log('Count---componentWillUnmount')}}//渲染组件ReactDOM.render(<Count count={ 199 } />, document.getElementById('test'))</script>
</body>
</html>

案例四:getSnapShotBeforeUpdate 的使用场景

展示新闻列表,1s向上追加一条新闻,并保证页面视图区域内容不变。

思路:

利用 getSnapShotBeforeUpdate() 获取组件更新之前 内容的 scrollHeight,传递给 componentDidUpdate()

组件更新之后,设置当前容器的 scrollTop 值为,当前内容高度 - 组件更新之前内容高度

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>4_getSnapShotBeforeUpdate的使用场景</title><style>.list {width: 200px;height: 150px;background-color: skyblue;overflow: auto;}.news {height: 30px;}</style>
</head>
<body><!-- 准备好一个“容器” --><div id="test"></div><!-- 引入react核心库 --><script type="text/javascript" src="../js/17.0.1/react.development.js"></script><!-- 引入react-dom,用于支持react操作DOM --><script type="text/javascript" src="../js/17.0.1/react-dom.development.js"></script><!-- 引入babel,用于将jsx转为js --><script type="text/javascript" src="../js/17.0.1/babel.min.js"></script><script type="text/babel">class NewsList extends React.Component {state = { newsArr: [] }componentDidMount() {setInterval(() => {const { newsArr } = this.state // 获取原状态const news = '新闻' + (newsArr.length + 1) // 模拟一条新闻this.setState({ newsArr: [news, ...newsArr] }) // 更新状态}, 1000)}getSnapshotBeforeUpdate() {return this.refs.list.scrollHeight}componentDidUpdate(preProps, preState, height) {this.refs.list.scrollTop += this.refs.list.scrollHeight - height}render() {return (<div className="list" ref="list">{this.state.newsArr.map((n, index) => {return <div key={index} className="news">{n}</div>})}</div>)}}ReactDOM.render(<NewsList />, document.getElementById('test'))</script>
</body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/107305.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一文理解登录鉴权(Cookie、Session、Jwt、CAS、SSO)

1 前言 登录鉴权是任何一个网站都无法绕开的部分&#xff0c;当系统要正式上线前都会要求接入统一登陆系统&#xff0c;一方面能够让网站只允许合法的用户访问&#xff0c;另一方面&#xff0c;当用户在网站上进行操作时也需要识别操作的用户&#xff0c;用作后期的操作审计。…

社区团购:优势、模式与未来发展趋势

随着互联网的普及和电子商务的快速发展&#xff0c;社区团购作为一种新兴的商业模式&#xff0c;正逐渐在各大城市流行起来。本文将详细阐述社区团购的基本概念、优势、模式以及未来发展趋势。 一、社区团购的基本概念和现状 社区团购是一种基于社区网络的电子商务模式&#…

docker jenkins

mkdir jenkins_home chown -R 1000:1000 /root/jenkins_home/docker run -d --name myjenkins -v /root/jenkins_home:/var/jenkins_home -p 8080:8080 -p 50000:50000 --restarton-failure jenkins/jenkins:lts-jdk17参考 Official Jenkins Docker imageDocker 搭建 Jenkins …

灾害与环境遥感团队本科生在IEEE TGRS 发表高水平论文

2023年9月27日&#xff0c;地球科学和遥感领域顶级期刊《IEEE Transactions on Geoscience and Remote Sensing》&#xff08;IEEE TGRS&#xff09;在线预刊发了灾害与环境遥感团队的最新研究成果“A novel spectral index for rapid dust-proof net mapping based on Sentine…

想做WMS仓库管理系统,找了好久才找到云表

公司内部仓库管理原方式均基于人工电子表格管理方式来实现收发存管理&#xff0c;没有流程化管理&#xff0c;无法保证数据的准确性和及时性&#xff0c;同时现场操作和数据核对会出现不同步的情况&#xff0c;无法提高仓库的运作效率&#xff0c;因此&#xff0c;我们基于云表…

【设计模式】单例模式、“多例模式”的实现以及对单例的一些思考

文章目录 1.概述2.单例模式实现代码2.1.饿汉式单例2.2.懒汉式单例2.3.双检锁单例2.4.静态内部类单例2.5.枚举单例 3.对单例的一些思考3.1.是否需要严格的禁止单例被破坏&#xff1f;3.2.懒汉式真的比饿汉式更佳吗&#xff1f;3.3.单例存在的问题 4.其他作用范围的单例模式4.1.线…

关闭VS Code中的鼠标悬停时的提示框(MDN Reference)

在使用VS Code编辑器写html文件时&#xff0c;鼠标悬停在写的某些内容时会弹出一个提示框&#xff0c;如下图&#xff1a; 这个提示是比较烦人的&#xff0c;接下来分享关闭它的教程&#xff1a; 这里是以Win10版的Visual Studio Code为例 1.打开VS Code 的设置界面 2.在扩展…

js构造函数

构造函数 通过 new 函数名 来实例化对象的函数叫构造函数。 任何的函数都可以作为构造函数存在。之所以有构造函数与普通函数之分&#xff0c;主要从功能上进行区别的&#xff0c;构造函数的主要 功能为 初始化对象&#xff0c;特点是和new 一起使用。new就是在创建对象&#x…

《开箱元宇宙》:《福布斯》如何通过 Web3 改进讲故事的方式

你们是否想知道 The Sandbox 如何融入世界上最具标志性的品牌和名人的战略&#xff1f;在本期《开箱元宇宙》系列中&#xff0c;我们与《福布斯》一起探讨了他们为何决定在 The Sandbox 中尝试 Web3&#xff0c;以及他们如何改变讲故事的方式&#xff0c;以便在一次体验中吸引超…

字节跳动2023测试开发岗 3+1 面经+经验分享(收到offer,入职月薪27K)

现在&#xff0c;招聘黄金时间已经来临&#xff0c;在网上看了很多大佬的面经&#xff0c;也加了很多交流群&#xff0c;受到了很多朋友的提点&#xff0c;今天终于轮到我来分享面经啦&#xff0c;之前面试了几家公司&#xff0c;最后在十月初拿到了字节跳动测试岗的 offer&…

口袋参谋:如何写出高权重标题?用对这招很重要!

​如何写出高权重标题&#xff1f;这是99.99%的卖家都存在的疑虑&#xff01; 以前写高权重标题&#xff0c;很多卖家往往会复制同行竞品爆款标题到淘宝首页搜索框&#xff0c;然后在全标题后面加上几个字母&#xff0c;就可以拆分爆款标题。 这个问题我之前也说过&#xff0…

【GO入门】环境配置及Vscode配置

1 GO环境配置 欢迎来到Go的世界&#xff0c;让我们开始探索吧&#xff01; Go是一种新的语言&#xff0c;一种并发的、带垃圾回收的、快速编译的语言。它具有以下特点&#xff1a; 它可以在一台计算机上用几秒钟的时间编译一个大型的Go程序。Go为软件构造提供了一种模型&…

【C++】:string用法详解

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关Linux的基础知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通 数…

使用PyTorch解决多分类问题:构建、训练和评估深度学习模型

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

编译linux内核模块时的make -C M= modules的参数说明

在linux下编译可加载内核模块形成.ko文件的makefile中的核心语句是&#xff1a; $(MAKE) -C $(KERNEL_DIR) M(PWD) modules 这句是Makefile的规则&#xff1a;这里的 $(MAKE)就相当于make;-C 选项的作用是指将当前工作目录转移到你所指定的位置&#xff0c;一般都是内核源代…

Vue配置全局变量config.js

Vue配置全局变量config.js 若config.js在public目录下 在index.html中引入 这样配置是为了防止路由前缀&#xff0c;如果直接“/config.js”&#xff0c;若路由没有前缀还好&#xff0c;要是有就需要配置为“<% BASE_URL %>config.js”

【01】基础知识:React简介与案例

一、React 简介 React 概述 React 是一个将数据渲染为 HTML 视图 的开源 JavaScript 库 React 由 FaceBook 开发&#xff0c;且开源 为什么要学习 React 1、原生 JavaScript 操作 DOM 繁琐、效率低&#xff08;使用 DOM-API 操作 UI&#xff09; 2、使用 JavaScript 直接…

Xilinx IP 10G Ethernet PCS/PMA IP Core

Vivado 10G Ethernet PCS/PMA介绍 1介绍 完整的10G以太网接口如下图,分为10G PHY和10G MAC两部分。 这篇文章重点讲 10G Ethernet PCS/PMA。 2 IP的基本介绍 10G以太网物理编码子层/物理介质连接(PCS/PMA)核心在Xilinx 10G以太网介质访问控制器(MAC)核心和具有10Gb/s…

Linux网络编程系列之UDP组播

Linux网络编程系列 &#xff08;够吃&#xff0c;管饱&#xff09; 1、Linux网络编程系列之网络编程基础 2、Linux网络编程系列之TCP协议编程 3、Linux网络编程系列之UDP协议编程 4、Linux网络编程系列之UDP广播 5、Linux网络编程系列之UDP组播 6、Linux网络编程系列之服务器编…

尚硅谷Flink(一)

目录 ☄️前置工作 fenfa脚本 &#x1f30b;概述 ☄️Flink是什么 ☄️特点&#xff08;多nb&#xff09; ☄️应用场景&#xff08;不用看&#xff09; ☄️分层API &#x1f30b;配环境 ☄️wordcount ☄️WcDemoUnboundStreaming &#x1f30b;集群部署 ☄️集…