千峰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 文…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...
篇章二 论坛系统——系统设计
目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...
JDK 17 序列化是怎么回事
如何序列化?其实很简单,就是根据每个类型,用工厂类调用。逐个完成。 没什么漂亮的代码,只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...
