React基础学习-Day02
React基础学习-Day02
1.受控表单绑定
在 React 中,受控表单(controlled form)是一种通过 React 组件状态(state)来管理表单元素值的方式。使用受控表单,可以将表单元素的值与 React 组件的状态保持同步,从而实现对表单数据的完全控制和管理。
如何创建受控表单
1. 输入框(Input)
使用 <input>
元素作为例子,展示如何创建一个受控输入框:
import React, { useState } from 'react';const ControlledFormExample = () => {// 定义一个状态变量来存储输入框的值const [inputValue, setInputValue] = useState('');// 处理输入框值变化的函数const handleInputChange = (event) => {setInputValue(event.target.value); // 更新状态变量的值};// 提交表单时处理函数const handleSubmit = (event) => {event.preventDefault(); // 阻止表单默认提交行为alert(`Submitted value: ${inputValue}`); // 弹出输入框的当前值};return (<form onSubmit={handleSubmit}><label>Input:<inputtype="text"value={inputValue} // 将输入框的值与状态变量绑定onChange={handleInputChange} // 处理输入框值变化的函数/></label><button type="submit">Submit</button></form>);
};export default ControlledFormExample;
2. 复选框(Checkbox)
对于复选框,需要注意初始状态和处理函数的变化:
import React, { useState } from 'react';const CheckboxExample = () => {// 定义一个状态变量来存储复选框的选中状态const [isChecked, setIsChecked] = useState(false);// 处理复选框状态变化的函数const handleCheckboxChange = (event) => {setIsChecked(event.target.checked); // 更新状态变量的值};// 提交表单时处理函数const handleSubmit = (event) => {event.preventDefault(); // 阻止表单默认提交行为alert(`Checkbox checked: ${isChecked}`); // 弹出复选框的当前选中状态};return (<form onSubmit={handleSubmit}><label>Checkbox:<inputtype="checkbox"checked={isChecked} // 将复选框的选中状态与状态变量绑定onChange={handleCheckboxChange} // 处理复选框状态变化的函数/></label><button type="submit">Submit</button></form>);
};export default CheckboxExample;
3. 下拉菜单(Select)
对于 <select>
元素,需要注意选项列表的处理和初始选中值:
import React, { useState } from 'react';const SelectExample = () => {// 定义一个状态变量来存储选择框的当前选中值const [selectedValue, setSelectedValue] = useState('option1');// 处理选择框选项变化的函数const handleSelectChange = (event) => {setSelectedValue(event.target.value); // 更新状态变量的值};// 提交表单时处理函数const handleSubmit = (event) => {event.preventDefault(); // 阻止表单默认提交行为alert(`Selected value: ${selectedValue}`); // 弹出选择框的当前选中值};return (<form onSubmit={handleSubmit}><label>Select:<select value={selectedValue} onChange={handleSelectChange}><option value="option1">Option 1</option><option value="option2">Option 2</option><option value="option3">Option 3</option></select></label><button type="submit">Submit</button></form>);
};export default SelectExample;
特点和优势
- 完全控制: 受控表单使得所有表单元素的值都由 React 组件状态管理,可以通过状态更新函数精确控制和验证输入。
- 一致性和可预测性: 因为状态直接驱动表单元素的值,所以可以确保表单的行为一致和可预测。
- 验证和处理: 可以轻松实现输入验证、条件渲染和复杂的表单逻辑,例如禁用按钮直到所有必填字段都填写完毕。
通过使用受控表单,React 组件能够更加灵活和可控地处理用户输入,提高了应用的可维护性和用户体验。
2.React中如何获取DOM
在 React 中获取 DOM 元素通常是通过 Refs(引用)来实现的。Refs 提供了一种直接访问在 render 方法中创建的 DOM 节点或 React 元素的方式。这种访问方式是为了避免直接操作 DOM,符合 React 的声明式和组件化的设计理念。
使用 Refs 获取 DOM
1. 创建 Refs
在函数式组件中,可以使用 useRef
钩子来创建 Ref 对象:
import React, { useRef } from 'react';const MyComponent = () => {// 创建一个 Ref 对象const myRef = useRef(null);// 在 useEffect 中操作 RefuseEffect(() => {console.log(myRef.current); // 输出 Ref 对象的当前值(关联的 DOM 节点)}, []);return (<div ref={myRef}>{/* 这里是组件内容 */}</div>);
};export default MyComponent;
2. 访问 DOM 节点
通过 ref.current
属性可以访问到 Ref 对象关联的 DOM 节点。需要注意的是,Ref 对象在组件的整个生命周期中保持不变,但 ref.current
的值会随着组件的渲染和卸载而变化。
3. 类组件中的 Refs
在类组件中,Refs 的创建和访问稍有不同:
import React, { Component } from 'react';class MyComponent extends Component {constructor(props) {super(props);// 创建一个 Ref 对象this.myRef = React.createRef();}componentDidMount() {console.log(this.myRef.current); // 输出 Ref 对象的当前值(关联的 DOM 节点)}render() {return (<div ref={this.myRef}>{/* 这里是组件内容 */}</div>);}
}export default MyComponent;
在类组件中,通过 React.createRef()
方法创建 Ref 对象,并在 componentDidMount
生命周期中访问 this.myRef.current
获取 DOM 节点。
使用场景
- 直接操作 DOM: 当需要在 React 中进行 DOM 操作时,例如测量元素尺寸、动画操作等,可以使用 Refs 来获取并操作 DOM 元素。
- 集成第三方库: 当需要与不支持 React 的第三方库(如 D3.js、Chart.js 等)集成时,Refs 提供了一种访问和控制 DOM 的方式。
- 焦点控制: 控制输入框、模态框等组件的焦点状态。
注意事项
- 避免滥用 Refs: 在大多数情况下,应该优先考虑使用 React 的数据驱动和状态管理方式,而不是直接操作 DOM。
- Refs 和函数式组件: 在函数式组件中,确保使用
useRef
钩子来创建 Ref 对象,而不是直接操作 DOM。
通过使用 Refs,在 React 中可以安全地获取和操作 DOM 元素,同时保持 React 的组件化和声明式编程模型的优势。
3.组件间通信
在 React 中,组件间通信是非常常见和重要的一部分,特别是在大型应用程序中,不同组件之间需要相互传递数据、状态或触发特定行为。以下是几种主要的 React 组件间通信方式:
1. Props 属性传递
Props(属性)是 React 中组件间通信最基础和常见的方式。通过将数据或函数作为属性传递给子组件,可以实现父组件向子组件的数据传递。
父组件传递数据给子组件:
// ParentComponent.jsx
import React from 'react';
import ChildComponent from './ChildComponent';const ParentComponent = () => {const data = 'Hello from parent';return (<div><ChildComponent message={data} /></div>);
};export default ParentComponent;
子组件接收并使用 Props 数据:
// ChildComponent.jsx
import React from 'react';const ChildComponent = (props) => {return (<div><p>{props.message}</p></div>);
};export default ChildComponent;
2. Callback 函数传递
通过将回调函数作为 Props 传递给子组件,子组件可以调用该函数并将数据或事件传递回父组件。
父组件定义回调函数并传递给子组件:
// ParentComponent.jsx
import React, { useState } from 'react';
import ChildComponent from './ChildComponent';const ParentComponent = () => {const [message, setMessage] = useState('');const handleCallback = (data) => {setMessage(data);};return (<div><p>Message from child: {message}</p><ChildComponent callback={handleCallback} /></div>);
};export default ParentComponent;
子组件调用回调函数并传递数据:
// ChildComponent.jsx
import React from 'react';const ChildComponent = (props) => {const sendDataToParent = () => {const data = 'Hello from child';props.callback(data);};return (<div><button onClick={sendDataToParent}>Send Data</button></div>);
};export default ChildComponent;
3. Context API
Context API 提供了一种在组件树中传递数据的方法,避免了通过 Props 层层传递数据的繁琐过程。适合在多层级嵌套的组件中使用,允许跨越组件层级直接传递数据。
创建 Context 对象并提供数据:
// MyContext.js
import React from 'react';const MyContext = React.createContext();export const MyProvider = MyContext.Provider;
export const MyConsumer = MyContext.Consumer;
使用 Context 提供数据并在子组件中消费:
// ParentComponent.jsx
import React from 'react';
import { MyProvider } from './MyContext';
import ChildComponent from './ChildComponent';const ParentComponent = () => {const data = 'Hello from context';return (<MyProvider value={data}><ChildComponent /></MyProvider>);
};export default ParentComponent;
在子组件中消费 Context 中的数据:
// ChildComponent.jsx
import React, { useContext } from 'react';
import { MyContext } from './MyContext';const ChildComponent = () => {const data = useContext(MyContext);return (<div><p>{data}</p></div>);
};export default ChildComponent;
4. Redux 或其他状态管理工具
对于大型应用程序中复杂的状态管理需求,可以使用 Redux 或其他状态管理工具(如 MobX)来集中管理应用程序的状态,并通过全局状态来实现组件间通信。这种方式适合需要多个组件共享状态或频繁更新状态的场景。
选择合适的通信方式
- Props 传递:简单、直观,适用于父子组件间的数据传递。
- Callback 函数:父组件可以向子组件传递函数来处理子组件中的事件,适合于子组件向父组件传递数据或事件。
- Context API:适用于跨组件层级传递数据,避免 Props 层层传递的麻烦。
- Redux 或其他状态管理工具:适用于需要全局状态管理或复杂的状态更新和同步需求的应用程序。
根据具体的场景和需求,选择适合的组件间通信方式是提高 React 应用开发效率和可维护性的关键。
4.useEffect
useEffect
是 React Hooks 中非常重要的一个钩子函数,用于在函数组件中执行副作用操作。副作用操作通常包括订阅数据、手动操作 DOM 和执行数据获取等。
基本用法
import React, { useEffect, useState } from 'react';const MyComponent = () => {// 定义一个状态来存储数据const [data, setData] = useState(null);// useEffect 第一个参数是一个函数,第二个参数是一个数组useEffect(() => {// 在组件加载后和每次更新后执行// 这里可以进行数据获取、订阅操作、手动 DOM 更新等异步操作fetchData();// 清理函数,可选,用于清理副作用return () => {cleanupFunction();};}, []); // 空数组意味着只在组件加载后执行一次const fetchData = async () => {// 异步操作示例,获取数据const result = await fetch('https://api.example.com/data');const data = await result.json();setData(data);};const cleanupFunction = () => {// 清理函数,比如清除订阅或取消定时器// 在组件卸载时执行};return (<div>{data ? (<p>Data loaded: {JSON.stringify(data)}</p>) : (<p>Loading...</p>)}</div>);
};export default MyComponent;
useEffect 的工作原理
- 第一个参数(effect):一个函数,包含需要执行的副作用操作,可以是数据获取、订阅操作、DOM 操作等异步任务。
- 第二个参数(dependencies 数组):可选参数,指定 effect 的依赖项。当依赖项发生变化时,effect 就会重新执行。如果不传递该参数,每次组件更新时都会执行 effect。
依赖项的作用
- 空数组
[]
:effect 仅在组件加载和卸载时执行,相当于componentDidMount
和componentWillUnmount
生命周期的结合体。 - 包含状态或属性的数组:effect 会在依赖项中的状态或属性发生变化时执行。比如
[count]
会在count
状态更新时执行 effect。 - 不传递第二个参数:effect 在每次组件更新时都会执行,相当于
componentDidUpdate
生命周期。
清理副作用
在 effect 函数中可以返回一个清理函数,用于清理副作用,比如取消订阅、清除定时器等。这样可以避免内存泄漏和无效的异步操作。
useEffect(() => {const subscription = subscribeToData();return () => {subscription.unsubscribe(); // 清理订阅};
}, [dependency]);
总结
useEffect
是 React Hooks 提供的强大工具,用于处理函数组件中的副作用操作。通过指定依赖项数组,可以精确控制 effect 的执行时机,避免不必要的重复执行,提高组件性能和可维护性。
5.自定义Hook
自定义 Hook 是 React 中的一个强大功能,它允许你将组件逻辑提取到可复用的函数中。自定义 Hook 的命名通常以 use
开头。
创建一个自定义 Hook
我们将创建一个简单的自定义 Hook useCounter
,它管理一个计数器的状态并提供增加和减少计数器的方法。
Step 1: 定义自定义 Hook
import { useState } from 'react';const useCounter = (initialValue = 0) => {const [count, setCount] = useState(initialValue);const increment = () => setCount(count + 1);const decrement = () => setCount(count - 1);return { count, increment, decrement };
};export default useCounter;
Step 2: 使用自定义 Hook
你可以在任意函数组件中使用这个自定义 Hook:
import React from 'react';
import useCounter from './useCounter';const CounterComponent = () => {const { count, increment, decrement } = useCounter(10);return (<div><p>Count: {count}</p><button onClick={increment}>Increment</button><button onClick={decrement}>Decrement</button></div>);
};export default CounterComponent;
自定义 Hook 的优势
- 逻辑复用:将重复使用的逻辑提取到自定义 Hook 中,使代码更加模块化和可复用。
- 更清晰的组件结构:通过将复杂逻辑抽离到自定义 Hook 中,组件代码变得更简洁和易读。
- 状态隔离:每次调用自定义 Hook 都会生成独立的状态,互不影响。
复杂的自定义 Hook 示例
创建一个自定义 Hook useFetch
来处理数据获取:
Step 1: 定义 useFetch
Hook
import { useState, useEffect } from 'react';const useFetch = (url) => {const [data, setData] = useState(null);const [loading, setLoading] = useState(true);const [error, setError] = useState(null);useEffect(() => {const fetchData = async () => {try {const response = await fetch(url);if (!response.ok) {throw new Error('Network response was not ok');}const data = await response.json();setData(data);} catch (error) {setError(error);} finally {setLoading(false);}};fetchData();}, [url]);return { data, loading, error };
};export default useFetch;
Step 2: 使用 useFetch
Hook
import React from 'react';
import useFetch from './useFetch';const DataComponent = () => {const { data, loading, error } = useFetch('https://api.example.com/data');if (loading) return <p>Loading...</p>;if (error) return <p>Error: {error.message}</p>;return (<div><pre>{JSON.stringify(data, null, 2)}</pre></div>);
};export default DataComponent;
总结
自定义 Hook 允许你将组件逻辑提取到可复用的函数中,提高代码的可读性和维护性。通过自定义 Hook,可以更方便地复用逻辑、管理复杂的状态和副作用,从而简化组件代码。
相关文章:
React基础学习-Day02
React基础学习-Day02 1.受控表单绑定 在 React 中,受控表单(controlled form)是一种通过 React 组件状态(state)来管理表单元素值的方式。使用受控表单,可以将表单元素的值与 React 组件的状态保持同步&a…...

切换网页visibilitychange,的升级版实现
目录 1 需求场景 2 用到的技术 3 日常检测方法 4 一个有意思的场景 5 升级版实现一 5.1 新建 /utils/browser.js 5.2 项目业务组件中使用 6 升级版实现二 6.1 安装js-tool-big-box工具库 6.2 引入 browserBox 对象 6.3 以控制累加定时器为例 6.4 查看定时器效果 1…...

基于pytesseract的OCR图片识别
简介 pytesseract是基于谷歌的tesseract的OCR包,支持识别一些简单的数字、字母、中文。 安装 安装引擎 下载地址:https://digi.bib.uni-mannheim.de/tesseract/ 一般是Windows 64位系统最新版: 如果要识别中文,注意选中中文…...
Docker_指令篇
Docker 的常用指令 1. 启动docker systemctl start docker2. 关闭docker systemctl stop docker3. 重启docker systemctl restart docker4. 设置自启动 systemctl enable docker5. 查看运行状态 systemctl status docker6. 查看帮助命令 docker pull --help7. 查看镜像 …...
HAL_UART_Transmit()函数用法
HAL_UART_Transmit函数用法 HAL_UART_Transmit()是 HAL 库中的一个函数,用于向指定的串口发送数据。它的函数原型如下: HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)其中各参数的含…...
OpenCV一个简单的摄像头调用与关闭
在使用OpenCV(Open Source Computer Vision Library)进行摄像头调用与关闭时,通常使用cv2.VideoCapture()函数来调用摄像头,并通过适当的方式关闭它。 调用摄像头 首先,需要导入OpenCV库(通常简写为cv2&a…...

深度学习5 神经网络
生物神经网络是指人的大脑,这是人工神经网络的技术原型。根据生物神经网络的原理,人们用计算机复现了简化的神经网络。当然,人工神经网络是机器学习的一大分支。 1.基本组成 1.1神 经 元 神经元是神经网络的基本组成。激活函数又称作激励函…...
js中! 、!!、?.、??、??=的用法及使用场景
js中! 、 !. 、!、?.、.?、??、??的用法及使用场景 !!!?.??????、?? 区别 !. (ts)注意 ! (非空断言符号) 用于取反一个布尔值或将一个值转换为布尔类型并取反 const a true; const b false; const value !a; // false const value !…...
嵌入式面试高频八股文面试题及参考答案
目录 什么是嵌入式系统?请简要描述其特点。 请解释实时操作系统(RTOS)的概念。 请列举几种常见的嵌入式操作系统。 请解释中断、异常和竞态条件在嵌入式系统中的作用。 什么是死锁?请举例说明如何避免死锁的发生。 请解释进程和线程的区别。 请解释同步和互斥的概念…...

前端练习小项目——方向感应名片
前言:在学习完HTML和CSS之后,我们就可以开始做一些小项目了,本篇文章所讲的小项目为——方向感应名片 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 在开始学习之前,先让我们看一…...
【Vim】为什么程序员喜欢用 Vim
1. Vim介绍 Vim是一款高度可配置的文本编辑器,它被设计成作为一个工具,可以非常高效地进行文本编辑工作。以下是关于Vim的一些基本介绍: 历史:Vim 是 Vi 文本编辑器的改进版,最初由布莱姆米勒(Bram Moole…...

stm32h743 NetXduo 实现http server CubeIDE+CubeMX
在这边要设置mpu的大小,要用到http server,mpu得设置的大一些 我是这么设置的,做一个参考 同样,在FLASH.ld里面也要对应修改,SECTIONS里增加.tcp_sec和 .nx_data两个区,我们用ram_d2区域去做网络,这个就是对应每个数据在d2区域的起点。 在CubeMX里,需要用到filex、dhc…...
ubuntu服务器部署vue springboot前后端分离项目
上传构建好的vue前端文件 vscode构建vue项目,会生成dist目录 npm run build在服务器root目录新建/projects/www目录,把dist目录下的所有文件,上传到此目录中 上传ssl证书 上传ssl证书到/projects目录中 配置nginx 编辑 /etc/nginx/site…...

【python】pandas报错:UnicodeDecodeError详细分析,解决方案以及如何避免
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...

FlinkModule加载HiveModule异常
HiveModule这个模块加载不出来 加在不出来这个模块,网上查说是要加下面这个依赖 <dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-hive_${scala.binary.version}</artifactId><version>${flink.…...

计算机硬件---如何更新自己电脑的BLOS
1找官网 例如“我使用的是HP(惠普)品牌的电脑”我只需要在浏览器上搜索“惠普官网”或“惠普-blos更新” 就可以看到,来自官网中更新blos的信息 2.有些品牌要查序列号该怎么办呢? 有许多方法可以查询,例如…...

AI算法17-贝叶斯岭回归算法Bayesian Ridge Regression | BRR
贝叶斯岭回归算法简介 贝叶斯岭回归(Bayesian Ridge Regression)是一种回归分析方法,它结合了岭回归(Ridge Regression)的正则化特性和贝叶斯统计的推断能力。这种方法在处理具有大量特征的数据集时特别有用ÿ…...

唯众物联网综合实训台 物联网实验室建设方案
物联网综合实训装置 物联网工程应用综合实训台是我公司针对职业院校物联网行业综合技能型人才培养,综合运用传感器技术、RFID技术、接口控制技术、无线传感网技术、Android应用开发等,配合实训台上的433M无线通信设备、ZigBee节点、射频设备、控制设备、…...
深入浅出 Vue.js:从基础到进阶的全面总结
深入浅出 Vue.js:从基础到进阶的全面总结 Vue.js 是一个用于构建用户界面的渐进式框架。它不仅易于上手,还能通过其强大的生态系统支持复杂的应用开发。本文将从基础到进阶,全面总结 Vue.js 的核心概念、常用技术和最佳实践,并提…...

路网双线合并单线——ArcGISpro 解决方法
路网双线合并成单线是一个在地图制作、交通规划以及GIS分析中常见的需求。双线路网定义:具有不同流向、不同平面结构的道路。此外,车道数较多的道路(例如,双黄实线车道数大于4的道路)也可以视为双线路网,本…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...