千峰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 文…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...

uniapp 小程序 学习(一)
利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 :开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置,将微信开发者工具放入到Hbuilder中, 打开后出现 如下 bug 解…...

使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...

基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)
引言 在嵌入式系统中,用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例,介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单,执行相应操作,并提供平滑的滚动动画效果。 本文设计了一个…...