千峰React:函数组件使用(2)
前面写了三千字没保存,恨!
批量渲染

function App() {const list = [{id:0,text:'aaaa'},{id:1,text:'bbbb'},{id:2,text:'cccc'}]// for (let i = 0; i < list.length; i++) {// list[i] = <li>{list[i]}</li>// }return (<div><ul>{list.map((item) => <li key={item.id}>{item.text}</li>)}</ul></div>)
}
export default App
点标记写法

// function Welcome() {
// return <div>hello Welcome</div>
// }// function App() {
// return (
// <div>
// <Welcome />
// <Welcome></Welcome>
// </div>
// )
// }
// export default Appconst Qf = () => {return <div>hello Qf</div>
}Qf.Welcome = () => {return <div>hello Welcome</div>
}function App() {return (<div><Qf.Welcome /><Qf.Welcome></Qf.Welcome></div>)
}
export default App
组件通信

import PropTypes from 'prop-types'
//子组件
function Welcome({ count, msg,isShow }) {return (<div>hello Welcome,{count},{msg},{isShow+''}</div>)
}// 添加 prop-types 验证
Welcome.propTypes = {count: PropTypes.string.isRequired, // 验证 count 是字符串并且是必传的msg: PropTypes.string.isRequired, // 验证 msg 是字符串并且是必传的isShow: PropTypes.string.isRequired, // 验证isShow是字符串并且是必传的
}//父组件
function App() {const count='我是个变量'return (<div><Welcome count={count} msg='hi react' isShow /></div>)
}
export default App
组件组合

import PropTypes from 'prop-types'
//子组件
function Welcome() {return <div>hello Welcome</div>
}function Head() {return <div>hello Head</div>
}// 添加 prop-types 验证
Welcome.propTypes = {count: PropTypes.string.isRequired, // 验证 count 是字符串并且是必传的msg: PropTypes.string.isRequired, // 验证 msg 是字符串并且是必传的isShow: PropTypes.string.isRequired, // 验证isShow是字符串并且是必传的
}//父组件
function App() {return (<div>hello App<Welcome><Head /></Welcome></div>)
}
export default App
可以看见这个Head被包在Welcome里 是渲染不出来的

使用props的children属性传递子组件
import PropTypes from 'prop-types'function Head() {return <div>hello Head</div>
}function Welcome({ children }) {return (<div>hello Welcome{children}</div>)
}// 添加 prop-types 验证
Welcome.propTypes = {count: PropTypes.string.isRequired, // 验证 count 是字符串并且是必传的children: PropTypes.string.isRequired,
}//父组件
function App() {return (<div>hello App<Welcome><Head /></Welcome></div>)
}
export default App

另一种写法
import PropTypes from 'prop-types'function Head({ count }) {return <div>hello Head,{count}</div>
}function Welcome() {const count = 456return (<div>hello Welcome<Head count={count} /></div>)
}
// 为 Head 组件添加 prop-types 验证
Head.propTypes = {count: PropTypes.number.isRequired, // 验证 count 是数字并且是必传的
}// 添加 prop-types 验证
Welcome.propTypes = {
}//父组件
function App() {return (<div>hello App<Welcome><Head /></Welcome></div>)
}
export default App

import PropTypes from 'prop-types'// 为 Head 组件添加 prop-types 验证
Head.propTypes = {count: PropTypes.number.isRequired, // 验证 count 是数字并且是必传的
}// 添加 prop-types 验证
Welcome.propTypes = {count: PropTypes.number.isRequired, // 验证 Welcome 组件的 count 是必传的
}function Head({ count }) {//接收countreturn <div>hello Head,{count}</div>
}function Welcome() {const count = 456return (<div>hello Welcome<Head count={count} />{/* {挂载count} */}</div>)
}//父组件
function App() {const count = 123return (<div>hello App<Welcome count={count} /></div>)
}
export default App
如何分别传递多组内容
所有的内容放到children里,没办法独立使用
import PropTypes from 'prop-types'function Welcome({ children }) {return (<div>{children}hello Welcome{children}</div>)
}// 添加 prop-types 验证
Welcome.propTypes = {count: PropTypes.string.isRequired, // 验证 count 是字符串并且是必传的children: PropTypes.string.isRequired,
}//父组件
function App() {return (<div>hello App<Welcome><div>aaaaaaaaaaaa</div><div>bbbbbbbbbbbb</div></Welcome></div>)
}
export default App

使用多组内容传递
import PropTypes from 'prop-types'function Welcome({ bottom, top }) {return (<div>{top}hello Welcome{bottom}</div>)
}// 添加 prop-types 验证
Welcome.propTypes = {count: PropTypes.string.isRequired, // 验证 count 是字符串并且是必传的children: PropTypes.string.isRequired,top: PropTypes.string.isRequired,bottom: PropTypes.string.isRequired,
}//父组件
function App() {return (<div>hello App<Welcometop={<div>aaaaaaaaaaaa</div>}bottom={<div>bbbbbbbbbbbb</div>}></Welcome></div>)
}
export default App

通信的数据如何添加默认值

import PropTypes from 'prop-types'function Welcome({ count, msg }) {return (<div>hello Welcome,{count},{msg}</div>)
}// 添加 prop-types 验证
Welcome.propTypes = {count: PropTypes.string.isRequired, // 验证 count 是字符串并且是必传的children: PropTypes.string.isRequired,msg: PropTypes.string.isRequired,
}//父组件
function App() {return (<div>hello App{/* { 传递参数的情况} */}<Welcome count={123} msg='hello react' />{/* { 不传递参数的情况} */}<Welcome /></div>)
}
export default App
如果有接收参数的位置,但是不传递参数,就会这样👇

为了解决这个问题,就提供了默认参数
ES6是这么做的:
import PropTypes from 'prop-types'// function Head() {
// return <div>hello Head</div>
// }function Welcome({ count='我是count的默认值', msg='我是msg的默认值'}) {return (<div>hello Welcome,{count},{msg}</div>)
}// 添加 prop-types 验证
Welcome.propTypes = {count: PropTypes.string.isRequired, // 验证 count 是字符串并且是必传的children: PropTypes.string.isRequired,msg: PropTypes.string.isRequired,
}//父组件
function App() {return (<div>hello App{/* { 传递参数的情况} */}<Welcome count={123} msg='hello react' />{/* { 不传递参数的情况} */}<Welcome /></div>)
}
export default App
也可以使用React原生的:
import PropTypes from 'prop-types'function Welcome({ count,msg}) {return (<div>hello Welcome,{count},{msg}</div>)
}// 添加 prop-types 验证
Welcome.propTypes = {count: PropTypes.number, // 验证 count 是数字(非必传)msg: PropTypes.string, // 验证 msg 是字符串(非必传)
}Welcome.defaultProps = {count: 0,msg:'我是默认值'
}
//父组件
function App() {return (<div>hello App{/* { 传递参数的情况} */}<Welcome count={123} msg='hello react' />{/* { 不传递参数的情况} */}<Welcome /></div>)
}
export default App
但是我失败了

为什么?因为:
我是19,别管了就用es6吧

通信数据如何限定类型

一般更推荐ts,但是ts不一定是项目用的
类型验证就用我之前已经写过的这部分👇
// 添加 prop-types 验证
Welcome.propTypes = {count: PropTypes.number, // 验证 count 是数字(非必传)msg: PropTypes.string, // 验证 msg 是字符串(非必传)
}
浏览器莫名其妙不报错,可能还是react的版本问题

如果希望有个数据传过来,数字和字符串都是符合要求的类型,也就是筛出两种类型可以这么写:
// 添加 prop-types 验证
Welcome.propTypes = {count:PropTypes.oneOfType([PropTypes.string,PropTypes.number,]),// 验证 count 是数字或字符串(非必传)msg: PropTypes.string, // 验证 msg 是字符串(非必传)
}
还可以有一些更复杂的限定,比如限定值是多少:
import PropTypes from 'prop-types'function Welcome({ count, msg }) {return (<div>hello Welcome,{count},{msg}</div>)
}// 添加 prop-types 验证
Welcome.propTypes = {count: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), // 验证 count 是数字或字符串(非必传)msg: PropTypes.string, // 验证 msg 是字符串(非必传)type: PropTypes.oneOf(['primary', 'success', 'error']),
}Welcome.defaultProps = {count: 0,msg: '我是默认值',
}
//父组件
function App() {return (<div>hello App{/* { 正确的情况} */}<Welcome count={123} msg='hello react' type='我是错的' /></div>)
}
export default App
这里按理来说应该会报错,但是并没有!!!

传值其实也可以传jsx:
import PropTypes from 'prop-types'function Welcome({ count, msg }) {return (<div>hello Welcome,{count},{msg}</div>)
}// 添加 prop-types 验证
Welcome.propTypes = {count: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), // 验证 count 是数字或字符串(非必传)msg: PropTypes.string, // 验证 msg 是字符串(非必传)type: PropTypes.oneOf(['primary', 'success', 'error']),icon: PropTypes.element//针对jsx的类型,element
}Welcome.defaultProps = {count: 0,msg: '我是默认值',
}
//父组件
function App() {return (<div>hello App{/* { 正确的情况} */}<Welcomecount={123}msg='hello react'type='primary'icon={<div className='icon-close'></div>}/></div>)
}
export default App
组件必须是个纯函数

react的严格模式会检测我们当前的组件是不是纯函数
纯函数组件是指:
组件的输出(渲染结果)完全由输入(props 和 state)决定。
组件没有副作用(例如直接修改 DOM、发起网络请求、使用
setTimeout等)。组件在相同的 props 和 state 下,总是返回相同的渲染结果
两次结果一样
在严格模式下,React 会 故意调用两次 函数组件(包括其渲染逻辑),如果组件是纯函数,两次调用的结果应该完全相同。
比如++操作,如果把对count的声明写函数外面,那么就不是一个纯函数:
预期来说count=2,最后等于3是因为React故意调用两次函数组件,两次的结果一次为2,一次为3,所以不是纯函数组件

这样就是了
function App() {let count = 1count++console.log(count)return <div>{count}</div>
}
export default App
两次结果相同

当然,不开严格模式的话就没有这种情况啦,一般建议开启
相同的输入和输出
意思就是给函数传入相同的参数,就应该传出相同的输出
这是一个纯函数,传入2都是4

这不是纯函数,传入2得到的输出不一定相同

纯函数可以保证我们的组件更健壮

组件的状态和useState
useState基础使用
useState 是一个 React Hook(函数),它允许我们向组件添加一个状态变量(State), 从而控制影响组件的渲染结果
状态变量是 React 组件内部的一个特殊变量,用于存储组件的数据,当状态变量的值发生变化时,React 会自动重新渲染组件,以反映最新的数据
状态变量和普通JS变量不同的是,状态变量一旦发生变化组件的视图UI也会跟着变化(数据驱动视图)
useState是React里的方法,返回的是个数组,数组里有两项:[状态变量,修改状态变量的方法]
只有用这个专门的修改状态变量的方法修改变量,才会在ui渲染里起效
//useState实现一个计数器按钮
import { useState } from 'react'
function App() {// const handleClick = (name,e) => console.log('button被点击了name:',name,'e:',e)//1、调用useState添加一个状态变量const [count, setCount] = useState(0)//2、点击事件回调const handleClick = () => { setCount(count+1) }return (<div className="App"><button onClick={handleClick}>{count}</button></div>);
}
export default App;
count++ 会直接修改 count 的值,而 React 的状态变量是不可变的(Immutable),不能直接修改。

那我就要问了:const handleClick = () => { setCount(count++) }这么写不也是通过setState 函数更新状态吗?为什么不行?

count++ 会先返回当前的值,再进行自增操作,而 React 的 setState 需要传入新的值,而不是修改原值。
那++count呢?++count 会先对 count 进行自增操作,然后返回自增后的值。这个操作会直接修改当前 count 的值,而 React 需要的是通过 setCount 来触发状态的更新,这就相当于状态变量的修改是你自己改的,不是通过对应的方法改的
正确的写法是应该直接传入 count + 1,而不是 count++,因为 count++ 只是修改了本地变量

对于对象来说也是这样,应该把新的对象写进对应方法,而不是直接修改
import { useState } from 'react'function App () {let [count, setCount] = useState(0)const handleClick = () => {// 直接修改 无法引发视图更新// count++// console.log(count)setCount(count + 1)}// 修改对象状态const [form, setForm] = useState({ name: 'jack' })const changeForm = () => {// 错误写法:直接修改// form.name = 'john'// 正确写法:setFrom 传入一个全新的对象setForm({...form,name: 'john'})}return (<div><button onClick={handleClick}>{count}</button><button onClick={changeForm}>修改form{form.name}</button></div>)
}export default App
![]()
状态如何改变视图

先看这段代码
function App() {let count = 0const increment = () => {count++ // 修改普通变量console.log(count) // 值会变化,但不会触发重新渲染}console.log(1234567)return (<div><p>{count}</p><button onClick={increment}>Increment</button></div>)
}
export default App
点击按钮时,count 的值会增加,但页面不会重新渲染,因此用户看不到变化。
状态变量会被记忆上一次的值,每次渲染函数返回的内容不一样,所以在察觉变化的时候React会重新调用渲染函数,并且改变count,所以每次结果都不一样)

普通变量的变化不会通知 React,所以React 不会调用渲染函数,所以不会重新渲染jsx。

顺便:Mujica第八集拍出来其实是为了缩短中国人寿命降低生产力,是日本人为了打败中国人投放的精神类武器,是日本成为东亚第一强国的邪恶计划最核心的一步
相关文章:
千峰React:函数组件使用(2)
前面写了三千字没保存,恨! 批量渲染 function App() {const list [{id:0,text:aaaa},{id:1,text:bbbb},{id:2,text:cccc}]// for (let i 0; i < list.length; i) {// list[i] <li>{list[i]}</li>// }return (<div><…...
DPVS-3: 双臂负载均衡测试
测试拓扑 双臂模式, 使用两个网卡,一个对外,一个对内。 Client host是物理机, RS host都是虚拟机。 LB host是物理机,两个CX5网卡分别在两个子网。 配置文件 用dpvs.conf.sample作为双臂配置文件,其中…...
2016年下半年试题二:论软件设计模式及其应用
论文库链接:系统架构设计师论文 论文题目 软件设计模式(Software DesignPatter)是一套被反复使用的、多数人知晓的、经过分类编目的代码设计经验的总结。使用设计模式是为了重用代码以提高编码效率增加代码的可理解性、保证代码的可靠性。软件设计模式是软件开发中的…...
深入理解 SQL 中的 DATEDIFF 函数
深入理解 SQL 中的 DATEDIFF 函数 DATEDIFF 函数在 SQL 中是一个用于计算两个日期之间差值的重要工具。不同数据库实现了不同版本的 DATEDIFF,它们在功能和语法上有所不同。本文将详细解析 DATEDIFF 的用法、数据库间差异、复杂场景中的应用,以及替代方…...
【第二节】C++设计模式(创建型模式)-抽象工厂模式
目录 引言 一、抽象工厂模式概述 二、抽象工厂模式的应用 三、抽象工厂模式的适用场景 四、抽象工厂模式的优缺点 五、总结 引言 抽象工厂设计模式是一种创建型设计模式,旨在解决一系列相互依赖对象的创建问题。它与工厂方法模式密切相关,但在应用…...
【学习资料】嵌入式人工智能Embedded AI
图片来源: Embedded Artificial Intelligence for Business Purposes | DAC.digital 随着AI在设备端的应用,我们看到越来越多的可穿戴设备出现以及自动驾驶汽车的发展,可以看到嵌入式人工智能是新的发展方向。我为大家介绍嵌入式人工智能的…...
【Python爬虫(60)】解锁社交媒体数据宝藏:Python爬虫实战攻略
【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取ÿ…...
C++ 继承,多态
看前须知: 本篇博客是作者听课时的笔记,不喜勿喷,若有疑问可以评论区一起讨论。 继承 定义: 继承机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段,它允许我们在保持原有 类特性的基础上进⾏扩展,增…...
Java中的Stream API:从入门到实战
引言 在现代Java开发中,Stream API 是处理集合数据的强大工具。它不仅让代码更加简洁易读,还能通过并行处理提升性能。本文将带你从基础概念入手,逐步深入Stream API的使用,并通过实战案例展示其强大功能。 1. 什么是Stream API…...
QPainter绘制3D 饼状图
先展示图片 核心代码如下: pie.h #ifndef Q3DPIE_H #define Q3DPIE_H#include <QtGui/QPen> #include <QtGui/QBrush>class Pie { public:double value; QBrush brush; QString description; double percentValue;QString p…...
【FAQ】HarmonyOS SDK 闭源开放能力 —Live View Kit (1)
1.问题描述: 客户端创建实况窗后,通过Push kit更新实况窗内容,这个过程是自动更新的还是客户端解析push消息数据后填充数据更新?客户端除了接入Push kit和创建实况窗还需要做什么工作? 解决方案: 通过Pu…...
数据治理与管理
引入 上一篇我们聊了数仓架构设计,它是企业构建数据中台的基石。其本质就是构建一个可靠易用的架构,可以借此将原始数据汇聚、处理,最终转换成可消费使用的数据资源。 在拥有数据资源以后,我们就需要考虑如何利用它,为企业创造价值,让它变成企业的资产而不是负担。也就…...
什么是HTTP/2协议?NGINX如何支持HTTP/2并提升网站性能?
HTTP/2是一种用于在Web浏览器和服务器之间进行通信的协议,旨在提高网站性能和加载速度。它是HTTP/1.1的继任者,引入了许多优化和改进,以适应现代Web应用的需求。HTTP/2的主要目标是减少延迟、提高效率,以及更好地支持并发请求。 …...
安全运维,等保测试常见解决问题。
1. 未配置口令复杂度策略。 # 配置密码安全策略 # vi /etc/pam.d/system-auth # local_users_only 只允许本机用户。 # retry 3 最多重复尝试3次。 # minlen12 最小长度为12个字符。 # dcredit-1 至少需要1个数字字符。 # ucredit-1 至少需要1个大…...
jmeter接口测试(二)
一、不同参数类型的接口测试 二、动态参数接口处理 随机数 工具——>函数助手对话框(Random 1000-10000之间的随机数 变量名为rdn)如下图所示 把上图生成的函数字符串复制到想要使用的地方如下图 三、断言 1、状态断言,200 不能证明…...
Keil ARM Complier Missing Compiler Version 5
使用Keil软件时出现了编译时报错,找不到对应的ARM版本,报错Target Target 1 uses ARM-Compiler Default Compiler Version 5 which is not available. *** Please review the installed ARM Compiler Versions: Manage Project Items - Folders/Extensions to manage ARM Compi…...
【僵尸进程】
【僵尸进程】 目录:知识点1. 僵尸进程的定义2. 僵尸进程产生的原因3. 僵尸进程的危害4. 如何避免僵尸进程 代码示例产生僵尸进程的代码示例避免僵尸进程的代码示例(父进程主动回收)避免僵尸进程的代码示例(信号处理) 运…...
【框架】参考 Spring Security 安全框架设计出,轻量化高可扩展的身份认证与授权架构
关键字:AOP、JWT、自定义注解、责任链模式 一、Spring Security Spring Security 想必大家并不陌生,是 Spring 家族里的一个安全框架,特别完善,但学习成本比较大,不少开发者都觉得,这个框架“很重” 他的…...
【Git 学习笔记_27】DIY 实战篇:利用 DeepSeek 实现 GitHub 的 GPG 密钥创建与配置
文章目录 1 前言2 准备工作3 具体配置过程3.1. 本地生成 GPG 密钥3.2. 导出 GPG 密钥3.3. 将密钥配置到 Git 中3.4. 测试提交 4 问题排查记录5 小结与复盘 1 前言 昨天在更新我的第二个 Vim 专栏《Mastering Vim (2nd Ed.)》时遇到一个经典的 Git 操作问题:如何在 …...
微信小程序地图map全方位解析
微信小程序地图map全方位解析 微信小程序的 <map> 组件是一个功能强大的工具,可以实现地图展示、定位、标注、路径规划等多种功能。以下是全方位解析微信小程序地图组件的知识点: 一、地图组件基础 1. 引入 <map> 组件 在页面的 .wxml 文…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
6.9-QT模拟计算器
源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...
2025年- H71-Lc179--39.组合总和(回溯,组合)--Java版
1.题目描述 2.思路 当前的元素可以重复使用。 (1)确定回溯算法函数的参数和返回值(一般是void类型) (2)因为是用递归实现的,所以我们要确定终止条件 (3)单层搜索逻辑 二…...
