当前位置: 首页 > news >正文

【React】03-React面向组件编程2

文章目录

    • 2.6. 组件的生命周期
      • 2.6.1. 效果
      • 2.6.2. 理解
      • 2.6.3. 生命周期流程图(旧)
      • 2.6.4. 生命周期流程图(新)
      • 2.6.5. ==重要的勾子==
      • 2.6.6. 即将废弃的勾子
      • 2.6.7 getSnapshotBeforeUpdate
    • 2.7. 虚拟DOM与DOM Diffing算法
      • 2.7.1. 效果
      • 2.7.2. 基本原理图

2.6. 组件的生命周期

2.6.1. 效果

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

  1. 让指定的文本做显示 / 隐藏的渐变动画
  2. 从完全可见,到彻底消失,耗时2S
  3. 点击“不活了”按钮从界面中卸载组件
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入三个库 -->
<script type="text/babel">class Demo extends React.Component{state = {opacity:1}death = ()=>{//卸载组件ReactDOM.unmountComponentAtNode(document.getElementById('test'))}//组件挂完毕componentDidMount(){console.log('componentDidMount');this.timer = setInterval(() => {//获取原状态let {opacity} = this.state//减小0.1opacity -= 0.1if(opacity <= 0) opacity = 1//设置新的透明度this.setState({opacity})}, 200);}//组件将要卸载componentWillUnmount(){//清除定时器clearInterval(this.timer)}//初始化渲染、状态更新之后render(){console.log('render');return(<div><h2 style={{opacity:this.state.opacity}}>React学不会怎么办?</h2><button onClick={this.death}>不活了</button></div>)}}//渲染组件到页面ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test'))
</script>

2.6.2. 理解

1.组件从创建到死亡它会经历一些特定的阶段。
2.React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用。
3.我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。

2.6.3. 生命周期流程图(旧)

生命周期的三个阶段(旧)

  1. 初始化阶段: 由ReactDOM.render()触发—初次渲染
    1.constructor()
    2.componentWillMount()
    3.render()
    4.componentDidMount()
  2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
    1.shouldComponentUpdate()=
    2.componentWillUpdate()
    3.render()
    4.componentDidUpdate()
  3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
    1.componentWillUnmount()
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入三个库 -->
<script type="text/babel">/* 1. 初始化阶段: 由ReactDOM.render()触发---初次渲染1.	constructor()2.	componentWillMount()3.	render()4.	componentDidMount() =====> 常用一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息2. 更新阶段: 由组件内部this.setSate()或父组件render触发1.	shouldComponentUpdate()2.	componentWillUpdate()3.	render() =====> 必须使用的一个4.	componentDidUpdate()3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发1.	componentWillUnmount()  =====> 常用一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息*/class Demo extends React.Component{constructor(props){console.log("Count---construtor");super(props)//初始化状态this.state = {count:0}}//加按钮的回调add = () =>{//获取原状态const {count} = this.state;this.setState({count:count+1})}//卸载组件按钮的回调dath = ()=>{React.unmountComponentAtNode(document.getElementById('test'))}//强制更新的按钮force = ()=>{this.forceUpdate()}//组件将要挂在的钩子函数componentWillMount(){console.log('Count---componentWillMount');}//组件挂在完毕componentDidMount(){console.log('Count---componentDidMount');}//组件将要卸载的钩子componentWillUnmount(){console.log('Count---componentWillUnmount');}//控制组件更新的阀门,默认为true,必须要有返回值shouldComponentUpdate(){console.log('Count---shouldComponentUpdate');return true}//组件将要更新的钩子componentWillUpdate(){console.log('Count---componentWillUpdate');}//组件更新完毕的钩子componentDidUpdate(){console.log('Count---componentDidUpdate');}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>)}     }//父组件Aclass 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>)}}//子组件Bclass B extends React.Component{//组件将要接收新的props的钩子componentWillReceiveProps(props){console.log('B---componentWillReceiveProps',props);}//控制组件更新的“阀门”shouldComponentUpdate(){console.log('B---shouldComponentUpdate');return true}//组件将要更新的钩子componentWillUpdate(){console.log('B---componentWillUpdate');}//组件更新完毕的钩子componentDidUpdate(){console.log('B---componentDidUpdate');}render(){console.log('B---render');return(<div>我是B组件,接收到的车是:{this.props.carName}</div>)}}//渲染组件到页面ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test'))
</script>

2.6.4. 生命周期流程图(新)

生命周期的三个阶段(新)

  1. 初始化阶段: 由ReactDOM.render()触发—初次渲染
    1.constructor()
    2.getDerivedStateFromProps
    3.render()
    4.componentDidMount()
  2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
    1.getDerivedStateFromProps
    2.shouldComponentUpdate()
    3.render()
    4.getSnapshotBeforeUpdate
    5.componentDidUpdate()
  3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
    1.componentWillUnmount()
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入三个库 -->
<script type="text/babel">/* 1. 初始化阶段: 由ReactDOM.render()触发---初次渲染1.	constructor()2.	getDerivedStateFromProps 3.	render()4.	componentDidMount() =====> 常用一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发1.	getDerivedStateFromProps2.	shouldComponentUpdate()3.	render()4.	getSnapshotBeforeUpdate5.	componentDidUpdate()3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发1.	componentWillUnmount()  =====> 常用一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息*/class Demo extends React.Component{//构造器constructor(props){console.log('Count---constructor');super(props)//初始化状态this.state = {count:0}}//加1按钮的回调add = ()=>{//获取原状态const {count} = this.state//更新状态this.setState({count:count+1})}//卸载组件按钮的回调death = ()=>{ReactDOM.unmountComponentAtNode(document.getElementById('test'))}//强制更新按钮的回调force = ()=>{this.forceUpdate()}//若state的值在任何时候都取决于props,那么可以使用getDerivedStateFromPropsstatic getDerivedStateFromProps(props,state){console.log('getDerivedStateFromProps',props,state);return null}//在更新之前获取快照getSnapshotBeforeUpdate(){console.log('getSnapshotBeforeUpdate');return 'atguigu'}//组件挂载完毕的钩子componentDidMount(){console.log('Count---componentDidMount');}//组件将要卸载的钩子componentWillUnmount(){console.log('Count---componentWillUnmount');}//控制组件更新的“阀门”shouldComponentUpdate(){console.log('Count---shouldComponentUpdate');return true}//组件更新完毕的钩子componentDidUpdate(preProps,preState,snapshotValue){console.log('Count---componentDidUpdate', preProps, preState, snapshotValue);}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>)}}//渲染组件到页面ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test'))
</script>

2.6.5. 重要的勾子

1.render:初始化渲染或更新渲染调用
2.componentDidMount:开启监听, 发送ajax请求
3.componentWillUnmount:做一些收尾工作, 如: 清理定时器

2.6.6. 即将废弃的勾子

1.componentWillMount
2.componentWillReceiveProps
3.componentWillUpdate

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

2.6.7 getSnapshotBeforeUpdate

<!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>

2.7. 虚拟DOM与DOM Diffing算法

2.7.1. 效果

需求:验证虚拟DOM Diffing算法的存在

2.7.2. 基本原理图

经典面试题:1). react/vue中的key有什么作用?(key的内部原理是什么?)2). 为什么遍历列表时,key最好不要用index?1. 虚拟DOM中key的作用:1) key是虚拟DOM对象的标识, 在更新显示时key起着极其重要的作用。2). 详细的说: 当状态中的数据发生变化时,react会根据【新数据】生成【新的虚拟DOM】, 随后React进行【新虚拟DOM】与【旧虚拟DOM】的diff比较,比较规则如下:a. 旧虚拟DOM中找到了与新虚拟DOM相同的key:(1).若虚拟DOM中内容没变, 直接使用之前的真实DOM(2).若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOMb. 旧虚拟DOM中未找到与新虚拟DOM相同的key根据数据创建新的真实DOM,随后渲染到到页面2. 用index作为key可能会引发的问题:1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。2. 如果结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题。3. 注意!如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。3. 开发中如何选择key?1.数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。2.如果确定只是简单的展示数据,用index也是可以的。

相关文章:

【React】03-React面向组件编程2

文章目录 2.6. 组件的生命周期2.6.1. 效果2.6.2. 理解2.6.3. 生命周期流程图(旧)2.6.4. 生命周期流程图(新)2.6.5. 重要的勾子2.6.6. 即将废弃的勾子2.6.7 getSnapshotBeforeUpdate 2.7. 虚拟DOM与DOM Diffing算法2.7.1. 效果2.7.2. 基本原理图 2.6. 组件的生命周期 2.6.1. 效…...

【python编程】python无法import模块的一种原因分析

python系统路径添加错误 报错原因原因分析解决办法补充 最近写代码的时候遇到一个问题&#xff0c;就是想添加工程下fu_convert文件夹下自己编写的convert_fw.py模块&#xff0c;但是出现报错&#xff0c;是个比较低级的问题&#xff0c;但还是简单记录一下 报错原因 无法找到…...

vue3.0与vue2.0的区别

前言 Vue 3.0是一个用于构建用户界面的JavaScript框架。相比于Vue 2.x&#xff0c;Vue 3.0在性能、体积和开发体验上都有了很大的提升。 以下将从不同的角度上去分析Vue 3.0与Vue 2.0的区别&#xff1a; 一、项目架构 从项目搭建和打包工具的选择来看&#xff1a; Vue 2.0 中…...

09_Webpack打包工具

1 初识Webpack 1.1 什么是Webpack Webpack打包工具对项目中的复杂文件进行打包处理&#xff0c;可以实现项目的自动化构建&#xff0c;并且给前端开发人员带来了极大的便利。 目前&#xff0c;企业中的绝大多数前端项目是基于Webpack打包工具来进行开发的。 1.2 Webpack的安…...

小程序 | 小程序后端用什么语言开发比较好

目录 ♣️ 引言 选择合适的后端语言 推荐使用Node.js Node.js 的优点 其他备选语言 ♣️ 小结 ♣️ 引言 小程序的兴起已经成为了当今移动互联网时代的热点之一&#xff0c;而小程序后端的好坏直接影响着小程序的使用体验&#xff0c;因此&#xff0c;选择一种好的语言来…...

Websocket升级版

之前写过一个关于websocket的博客&#xff0c;是看书时候做的一个demo。但是纸上得来终觉浅&#xff0c;这次实战后实打实的踩了不少坑&#xff0c;写个博客记录总结。 1.安装postman websocket接口调试&#xff0c;需要8.5以及以上版本的postman 先把以前的卸载&#xff0c…...

基于音频SOC开发板的主动降噪ANC算法源码实现

基于音频SOC开发板的主动降噪ANC算法源码实现 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群附加赠送降噪开发资料,...

【Pytorch】深度学习之损失函数

文章目录 二分类交叉熵损失函数交叉熵损失函数L1损失函数MSE损失函数平滑L1(Smooth L1)损失函数目标泊松分布的负对数似然损失KL散度MarginRankingLoss多标签边界损失函数二分类损失函数多分类的折页损失三元组损失HingEmbeddingLoss余弦相似度CTC损失函数参考资料 学习目标&am…...

3.4 构造方法

思维导图&#xff1a; 3.4.1 定义构造方法 ### Java中的构造方法 #### **定义与目的** 构造方法&#xff0c;也称为构造器&#xff0c;是一个特殊的成员方法&#xff0c;用于在实例化对象时为对象赋值或执行初始化操作。其主要目的是确保对象在被创建时具有有效和合适的初始状…...

代码随想录

前言 代码随想录算法训练营day43 一、Leetcode 1049. 最后一块石头的重量 II 1.题目 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分…...

2核4G游戏服务器推荐(阿里云/腾讯云/华为云)

2核4G游戏服务器推荐&#xff0c;首选腾讯云2核4G5M带宽轻量应用服务器218元一年、阿里云2核4G4M带宽轻量应用服务器297元一年&#xff0c;华为云2核2G3M云耀L服务器95元一年&#xff0c;阿腾云来详细说下2核4G游戏服务器推荐配置大全&#xff1a; 目录 2核4G游戏服务器推荐 …...

SQL标识列实现自动编号的步骤和技巧以及优势

目录 前言: 过程: 1.步骤: 2.标识种子和表示增量: 效果展示:​ 优势: 总结: 前言: 在.NET中的例子里面遇到这么一个问题&#xff0c;不能将NULL插入列‘ID’&#xff0c;表Login.dbo.Scores’;列不允许有NULL值。INSERT失败。这个问题很明显&#xff0c;我在SQL数据库中…...

【Debian】报错:su: Authentication failure

项目场景&#xff1a; 今天我重新刷了一个debian系统。 系统版本&#xff1a; # 查看系统版本 lsb_release -a 我的系统版本&#xff1a; No LSB modules are available. Distributor ID&#xff1a;Debian Description: Debian GNU/Linux 12 &#xff08;bookworm&#xff…...

我测试用的mark down教程

Markdown 教程 欢迎使用 Markdown 你好,Markdown是一种类似 Word 的排版工具,你需要仔细阅读这篇文章,了解一下 Markdown 基础知识。 Markdown 功能和列表演示 Markdown 有以下功能,帮助你用它写博客: 数学公式代码高亮导航功能等等Markdown 的优点: 间接高效大厂支持…...

网络编程基础知识总结——IP,端口,协议

目录 1. 什么是网络编程&#xff1f; 2. 网络编程的三要素 3. IP 3.1 IP地址的概念 3.2 IP地址的分类 3.3 IPv4解析 3.4 Ipv6解析 4. IPv4 的使用细节 5. 特殊IP地址 4. 端口号 5. 协议 5.1 UDP协议 5.2 TCP协议 1. 什么是网络编程&#xff1f; 总的来说就是一句…...

【LeetCode力扣】297. 二叉树的序列化与反序列化

目录 1、题目介绍 2、解题思路 2.1、详细过程图解 2.2、代码描述 2.3、完整代码 1、题目介绍 原题链接&#xff1a;297. 二叉树的序列化与反序列化 - 力扣&#xff08;LeetCode&#xff09; 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,null,null,4,5] 输出&#…...

Linux寄存器+Linux2.6内核进程调度队列+命令行参数+环境变量

目录 一、寄存器 二、Linux2.6内核进程调度队列 &#xff08;一&#xff09;优先级 &#xff08;二&#xff09;活动队列 &#xff08;三&#xff09;过期队列 &#xff08;四&#xff09;active指针和expired指针 三、命令行参数 &#xff08;一&#xff09;举例一 &…...

组合数(2)获取C(n,k)组合数列表的QT实现

1)工程文件 QT coreCONFIG c17 cmdline# You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES QT_DISABLE_DEPRECATED_BEFORE0x060000 # disables all the APIs deprecated before Qt 6.…...

SparkCore编程RDD

RDD概述 中文名为弹性分布式数据集&#xff0c;是数据处理基本单位。代表一个弹性的&#xff0c;不可变&#xff0c;可分区&#xff0c;里面的数据可并行计算的集合。 RDD和Hadoop MR 的区别&#xff1a; RDD是先明确数据处理流程&#xff0c;数据在行动算子执行前实际上并未…...

VBA技术资料MF69:添加和删除工作表中的分页符

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。我的教程一共九套&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到…...

数字技术助力智慧公厕,让公厕变身为全新创新应用

在如今数字化的时代&#xff0c;数字技术的集成应用已经渗透到了生活的方方面面。其中一个令人瞩目的领域就是智慧公厕。以前只是简单的厕所&#xff0c;如今借助数字技术的力量&#xff0c;智慧公厕变得功能强大、智能高效。接下来&#xff0c;我们将以智慧公厕源头领航厂家广…...

electron 升级 v22 遇到问题

Electron 漏洞 https://mp.weixin.qq.com/s/5LpSJb_5uV8EIDOl3fz9Tw 由于 23以上不在支持win 7 8 8.1 所以我选择安装 v22.3.24 electron 22.3.24 node-sass 6.0.1 sass-loader 10.4.1 对应的版本 npm i node-sass6.0.1 --sass_binary_sitehttps://npm.taobao.org/mirrors…...

跟我学c++中级篇——Pimpl

一、前向声明 前向声明或者前置声明(forward declaration)&#xff0c;这个在c中用得还是比较多的。一般的框架或者库中&#xff0c;经常可以看到在一个类的前面声明了一个类&#xff0c;类似下面这样&#xff1a; class useclass; class mycall{...useclass *us; };前向声明…...

[补题记录] Atcoder Beginner Contest 295(E)

URL&#xff1a;https://atcoder.jp/contests/abc295 目录 E Problem/题意 Thought/思路 Code/代码 E Problem/题意 给定长度为 N 的数组 A。进行如下操作&#xff1a; 若 Ai 0&#xff0c;将 Ai 等概率地变为 1 ~ M 中的任意一个数&#xff1b;对 A 排序&#xff1b; …...

解决git在window11操作很慢,占用很大cpu的问题

【git在window11操作很慢&#xff0c;占用很大cpu&#xff0c;最后也执行失败】 在谷歌输入&#xff1a;git very slow in window 11。通过下面链接终于找到了解决方案&#xff1a; https://www.reddit.com/r/vscode/comments/sulebx/slow_git_in_wsl_after_updating_to_window…...

C++智能指针(二)——weak_ptr初探

文章目录 1. shared_ptr 存在的问题2. 使用weak_ptr2.1 初始化 weak_ptr2.2 访问数据 3. 附录4. 参考文献 1. shared_ptr 存在的问题 与 shared_ptr 的引入要解决普通指针存在的一些问题一样&#xff0c;weak_ptr 的引入&#xff0c;也是因为 shared_ptr 本身在某些情况下&…...

540 - Team Queue (UVA)

题目链接如下&#xff1a; Online Judge 对比刘汝佳的代码&#xff0c;我没有用queue来排整个队伍&#xff0c;因为那样的话遍历整个队伍太麻烦&#xff0c;vector比较方便。但vector删除元素比较耗时&#xff0c;所以就不删了&#xff0c;仅仅用pivot来指代目前队伍的开始。…...

投资组合之如何估值

文章目录 如何估值一、PE估值法1、PE估值法的定义2、参考标准&#xff08;1&#xff09;常规标准&#xff1a;25倍合理市盈率。&#xff08;2&#xff09;同行业对比。&#xff08;3&#xff09;跟历史市盈率相比。 3、PE估值法的适用范围4、PE估值法的优势5、PE估值法的劣势&a…...

2024届通信工程保研经验分享(预推免入营即offer)

2024届通信工程保研经验分享&#xff08;预推免入营即offer&#xff09; BackGround夏令营情况&#xff1a;预推免情况&#xff1a; BackGround 本科院校&#xff1a;末九 专业&#xff1a;通信工程 rank&#xff1a;3/123&#xff08;预推免绩点排名&#xff09;&#xff0…...

L2-025 分而治之 - java

L2-025 分而治之 时间限制 600 ms 内存限制 64 MB 题目描述&#xff1a; 分而治之&#xff0c;各个击破是兵家常用的策略之一。在战争中&#xff0c;我们希望首先攻下敌方的部分城市&#xff0c;使其剩余的城市变成孤立无援&#xff0c;然后再分头各个击破。为此参谋部提供了若…...