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

react中ref的使用(useRef,forwardRef,useImperativeHandle,createRef)

文章目录

  • 一、什么是ref
  • 二、在函数式组件中使用ref
    • 1. useRef 获取dom
    • 2. forwardRef获取子组件的dom
    • 3. useImperativeHandle将某些指定的行为暴露给父组件
  • 三、在类组件中使用ref
    • 1. createRef
    • 2. 回调函数
    • 3. 字符串

一、什么是ref

在React中,ref是一个用于访问真实DOM节点或者React组件实例的对象。它允许您在组件中直接操作DOM元素或组件,而无需遵循传统的数据流。

使用ref,您可以:

  1. 访问和操作DOM:ref允许您通过将ref对象传递给组件中的元素来访问和修改真实的DOM。您可以使用ref来获取输入框的值、改变元素的样式、添加/删除/更新元素等等。

  2. 访问和调用组件方法:ref允许您访问在组件类上定义的方法。这对于在某些情况下需要从父组件中直接访问子组件的方法非常有用。

  3. 获取组件实例和进行事件监听:当使用类组件时,ref可以用来获取组件的实例,以便在需要时进行其他操作。您还可以使用ref来进行事件监听,例如在某个特定的事件发生时执行某些操作。

需要注意的是,在大多数情况下,最好遵循React的数据流原则,尽量避免直接操作DOM或访问子组件的方法。只有当没有其他合适的选择并且确实需要这样做时,才应该使用ref。因为直接操作DOM或访问子组件的方法可能会破坏组件的封装性和可重用性。

二、在函数式组件中使用ref

1. useRef 获取dom

在React中,函数式组件使用ref属性可以获取到组件的实例或者某个Dom元素的引用。使用ref可以让你更方便地控制组件或Dom元素,并且可以在需要的时候访问和修改它们的属性和方法。

要在函数式组件中使用ref,你可以使用React提供的useRef钩子函数。举一个例子,假设我们有一个函数式组件MyComponent,其中包含了一个input元素:

import React, { useRef } from 'react';const MyComponent = () => {const inputRef = useRef(null);const handleClick = () => {// 使用 useRef 返回的 ref 对象来访问 input 的属性和方法console.log(inputRef.current.value);inputRef.current.focus();};return (<div><input ref={inputRef} type="text" /><button onClick={handleClick}>Focus Input</button></div>);
};export default MyComponent;

上述例子中,我们使用useRef钩子函数来创建了一个名为inputRef的引用。我们将这个引用传递给了input元素的ref属性,这样就可以通过inputRef.current来获取该input的引用。

在函数式组件的handleClick函数中,我们可以通过inputRef.current访问到input元素并获取到它的值。我们还可以使用inputRef.current.focus()来让input元素获得焦点。

通过使用ref,我们可以方便地操纵组件或Dom元素,进行一些需要访问或修改属性和方法的操作。
注意,ref只能在函数式组件中使用,并且不能在函数式组件的子组件上使用

2. forwardRef获取子组件的dom

在React中,函数式组件的子组件上可以使用forwardRef来使用refforwardRef函数可以将ref传递给子组件,从而在子组件中使用ref

下面是一个示例,展示了如何在函数式组件的子组件中使用ref

import React, { forwardRef } from 'react';// 子组件
const ChildComponent = forwardRef((props, ref) => {return (<input type="text" ref={ref} />);
});// 父组件
const ParentComponent = () => {// 创建一个refconst inputRef = React.createRef();// 使用ref传递给子组件return (<div><ChildComponent ref={inputRef} /><button onClick={() => inputRef.current.focus()}>聚焦输入框</button></div>);
};export default ParentComponent;

在上面的例子中,ChildComponent是一个函数式组件,通过将ref作为forwardRef的第二个参数,将其传递给内部的input元素。然后,可以在ParentComponent中创建一个ref并将其传递给ChildComponent。这样,我们就可以在父组件中操作子组件的input元素,例如调用focus()方法。

在按钮的onClick事件处理函数中,我们可以通过inputRef.current来获得子组件的input元素,并调用它的focus()方法将焦点聚焦到输入框上。

3. useImperativeHandle将某些指定的行为暴露给父组件

在React中,通过使用useImperativeHandle钩子函数,函数式组件可以将某些指定的行为暴露给父组件。这在一些情况下非常有用,例如限制某些DOM行为,让父组件能够直接操作该组件的某些功能。

下面是一个例子,演示如何使用useImperativeHandle来限制DOM行为:

import React, { useRef, useImperativeHandle, forwardRef } from 'react';// 子组件
const ChildComponent = forwardRef((props, ref) => {const childRef = useRef(null);// 定义待暴露的函数useImperativeHandle(ref, () => ({// 在这里暴露特定的DOM行为focus: () => {childRef.current.focus();},// 在这里暴露特定的DOM行为blur: () => {childRef.current.blur();}}));return <input ref={childRef} />;
});// 父组件
const ParentComponent = () => {const childRef = useRef(null);const handleFocus = () => {childRef.current.focus();  // 子组件的focus函数被父组件调用};const handleBlur = () => {childRef.current.blur();   // 子组件的blur函数被父组件调用};return (<div><ChildComponent ref={childRef} /><button onClick={handleFocus}>Focus</button><button onClick={handleBlur}>Blur</button></div>);
};export default ParentComponent;

在上面的例子中,ChildComponent是一个简单的函数式组件,它包含了一个<input>元素。通过使用useImperativeHandle钩子函数,并将ref作为第一个参数传递进去,我们可以定义需要暴露给父组件的函数(在这里是focusblur)。这意味着父组件可以通过ref引用子组件,然后直接调用子组件的focusblur函数。

ParentComponent中,通过使用useRef来创建一个childRef引用。然后,在handleFocushandleBlur函数中,通过childRef.current来访问ChildComponent函数组件的focusblur函数,从而直接操控子组件的DOM行为。

这样,我们就可以在父组件中通过按钮点击来控制子组件的DOM行为,实现了对DOM行为的限制。

三、在类组件中使用ref

1. createRef

在类式组件中,可以使用React.createRef()来创建一个ref对象,然后将该ref对象附加到component的一个元素上,通过ref对象可以引用该元素并对其进行操作。

下面是一个使用ref的示例:

import React from "react";class MyComponent extends React.Component {constructor(props) {super(props);this.myDivRef = React.createRef(); // 创建一个ref对象}handleClick = () => {this.myDivRef.current.style.backgroundColor = "blue"; // 使用ref对象引用元素并对其进行操作}render() {return (<div><div ref={this.myDivRef}>Hello, world!</div> {/* 将ref对象附加到元素上 */}<button onClick={this.handleClick}>Change Color</button></div>);}
}export default MyComponent;

在上面的示例中,我们首先在类的构造函数中创建一个ref对象myDivRef。然后,通过将myDivRef作为<div>元素的ref属性值,我们可以将ref对象附加到这个元素上。在handleClick方法中,我们通过this.myDivRef.current引用该元素并改变其背景颜色为蓝色。

这样,当点击按钮时,就会调用handleClick方法,从而改变被ref引用的<div>元素的背景颜色。

2. 回调函数

通过回调函数来设置ref,在回调函数中将DOM元素分配给组件的实例属性。在组件的实例中,可以通过属性来访问该DOM元素。

import React, { Component } from 'react';class ExampleComponent extends Component {constructor(props) {super(props);this.myRef = null;this.setRef = element => {this.myRef = element;};}componentDidMount() {console.log(this.myRef); // 访问DOM元素}render() {return <div ref={this.setRef}>Example</div>;}
}

3. 字符串

使用字符串的ref属性来获取DOM元素。这种方式在React v16.3之前是支持的,但在较新的版本中已经过时,不建议使用。

import React, { Component } from 'react';class ExampleComponent extends Component {componentDidMount() {console.log(this.refs.myRef); // 访问DOM元素}render() {return <div ref="myRef">Example</div>;}
}

相关文章:

react中ref的使用(useRef,forwardRef,useImperativeHandle,createRef)

文章目录 一、什么是ref二、在函数式组件中使用ref1. useRef 获取dom2. forwardRef获取子组件的dom3. useImperativeHandle将某些指定的行为暴露给父组件 三、在类组件中使用ref1. createRef2. 回调函数3. 字符串 一、什么是ref 在React中&#xff0c;ref是一个用于访问真实DO…...

正点原子嵌入式linux驱动开发——Linux USB驱动

USB是很常用的接口&#xff0c;目前大多数的设备都是USB接口的&#xff0c;比如鼠标、键盘、USB摄像 头等&#xff0c;在实际开发中也常常遇到USB接口的设备&#xff0c;本章就来学习一下如何使能Linux内核自带的USB驱动。这里不会具体学习USB的驱动开发。 USB接口简介 什么是…...

(四)docker:为mysql和java jar运行环境创建同一网络,容器互联

看了很多资料&#xff0c;说做互联的一个原因是容器内ip不固定&#xff0c;关掉重启后如果有别的容器启动&#xff0c;之前的ip会被占用&#xff0c;所以做互联创建一个网络&#xff0c;让几个容器处于同一个网络&#xff0c;就可以互联还不受关闭再启动ip会改变的影响&#xf…...

【kafka】记一次kafka基于linux的原生命令的使用

环境是linux&#xff0c;4台机器&#xff0c;版本3.6&#xff0c;kafka安装在node 1 2 3 上&#xff0c;zookeeper安装在node2 3 4上。 安装好kafka&#xff0c;进入bin目录&#xff0c;可以看到有很多sh文件&#xff0c;是我们执行命令的基础。 启动kafka&#xff0c;下面的…...

C语言或C++结构体及其变量的创建方式汇总

第一种&#xff1a; struct 结构体类型名{ 任意类型 变量&#xff1b; }; 结构体类型名 *结构体变量new 结构体类型名; #include<bits/stdc.h> using namespace std; struct LNode {int data;struct LNode *next; }; /*void PutElem(LNode *t){while(t->next!NULL){…...

mysql之基础语句

数据库的列类型 int&#xff1a;整型 用于定义整数类型的数据 float&#xff1a;单精度浮点4字节32位 准确表示到小数点后六位 double&#xff1a;双精度浮点8字节64位 char&#xff1a;固定长度的字符类 用于定义字符类型数据&…...

Sentinel 哨兵数据 更新下载地址 2023年11月

1. 欧空局官方下载 2023年11月开始&#xff0c;原来欧空局的下载地址和应用有了变化&#xff0c;现在迁移到以下新地址下载&#xff1a; https://dataspace.copernicus.eu/ 我这边测试需要重新注册用户才能进行登录和使用&#xff0c;界面使用和之前差不多&#xff0c;具体操作…...

动态路由协议OSPF项目部署(二)

1. 静态和动态路由的区别&#xff1b; 2. OSPF协议通信过程与部署&#xff1b; 3. OSPF协议在项目上的应用场景 - OSPF - 开放式最短路径优先 - 一个动态路由协议 - 路由器转发数据 - 路由器需要一张地图 - 路由表 - 路由表如何构建的&#xff1f; - 依靠手动 或…...

winscp文件增量同步到linux服务器

一&#xff0c;点击同步 场景&#xff1a;在做服务器迁移的时候&#xff0c;文件好几十个G一天也迁移不完&#xff0c;每天还有增量的文件&#xff0c;先全量同步一次&#xff0c;然后再用增量同步&#xff0c;然后你用winscp的同步工具&#xff0c;进增量同步。 将本地文件同…...

足足68个!Python函数合集请收好!

内置函数就是python给你提供的, 拿来直接用的函数&#xff0c;比如print.&#xff0c;input等。 #68个内置函数 # abs()   dict()   help()   min()   setattr() # all()   dir()   hex()   next()   sli…...

vue2.0 打包,nginx部署

1、修改这里为空 否则报错&#xff1a;vue is undefined 2、修改为hash&#xff0c;重点&#xff1a;打包dist文件运行&#xff0c;必须这样 3、安装ngnix&#xff0c;重点&#xff1a;使用node的包&#xff1a;httpserve&#xff0c;失败 4、重点&#xff1a;配置代理转发 前端…...

微服务架构之路1,服务如何拆分?使用微服务的注意事项?

目录 一、前言二、单体服务的弊端三、微服务化四、服务如何拆分&#xff1f;五、使用微服务的注意事项1、服务如何定义2、服务如何发布和订阅3、服务如何监控4、服务如何治理5、故障如何定位 大家好&#xff0c;我是哪吒。 一、前言 微服务已经是Java开发的必备技能&#xff…...

解决Mac电脑音乐显示歌名的乱码问题

最近想听「万能青年旅店」的歌&#xff0c;结果在Mac电脑的「音乐」里面打开后是乱码。 【原因】(求助于chatGPT) 乱码问题可能是由于MP3文件的元数据&#xff08;比如歌曲名、艺术家、专辑等信息&#xff09;的编码问题导致的。如果这些信息是用非标准的或者不兼容的字符编码…...

赢在电商设计!2024年最新电商设计实战技巧盘点

双十一、双十二、黑五的电商大促即将轮番将至&#xff0c;电商运营人迎来大忙季&#xff0c;选品、直播、采购入库、售后……各种环节都是影响电商转化的关键因素&#xff0c;而电商设计作为打通这些环节&#xff0c;打造高转化率电商平台的关键要素&#xff0c;能够吸引用户注…...

约数之和 (普通快速幂求逆元做法)

假设现在有两个自然数 A 和 B&#xff0c;S 是 AB 的所有约数之和。 请你求出 Smod9901 的值是多少。 输入格式 在一行中输入用空格隔开的两个整数 A 和 B 。 输出格式 输出一个整数&#xff0c;代表 Smod9901 的值。 数据范围 0≤A,B≤5107 输入样例&#xff1a; …...

每日一题(LeetCode)----二分查找(三)

每日一题(LeetCode)----二分查找&#xff08;三&#xff09; 1.题目&#xff08;69. x 的平方根 &#xff09; 给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。 由于返回类型是整数&#xff0c;结果只保留 整数部分 &#xff0c;小数部分将被 舍去 。 **注意…...

使用 TensorFlow FasterRCNN 网络进行目标检测

目录 描述 此示例的工作原理 处理输入图形 数据准备 sampleUffFasterRCNN 插件 验证输出 TensorRT API 层和操作 TensorRT API 层和操作 先决条件 运行示例 示例 --help 选项 附加资源 许可 变更记录 已知问题 本示例&#xff0c;sampleUffFasterRCNN&#xff0…...

数据结构——顺序表(SeqList)

目录 1. 顺序表介绍 2. 顺序表工程 2.1 顺序表定义 2.1.1 静态顺序表 2.1.2 动态顺序表 2.2顺序表接口 2.2.1 顺序表初始化 2.2.2 顺序表打印 2.2.3 顺序表销毁 2.2.4 顺序表数据插入 2.2.4.1 容量检查 2.2.4.2 顺序表尾插 2.2.4.3 顺序表头插 2.2.4.4 顺序表随机…...

Uni-App 快捷登录

uniapp 实现一键登录前置条件: 开通uniCloud, 开通一键登录功能参考的文档 : 官网 - 一键登录uniapp指南 : https://uniapp.dcloud.net.cn/univerify.html#%E6%A6%82%E8%BF%B0 官网 - 一键登录开通指南 : https://ask.dcloud.net.cn/article/37965 官网 - unicloud使用指南 htt…...

DbUtils + Druid 实现 JDBC 操作 --- 附BaseDao

文章目录 Apache-DBUtils实现CRUD操作1 Apache-DBUtils简介2 主要API的使用2.1 DbUtils2.2 QueryRunner类2.3 ResultSetHandler接口及实现类 3 JDBCUtil 工具类编写3.1 导包3.2 编写配置文件3.3 编写代码 4 BaseDao 编写 Apache-DBUtils实现CRUD操作 1 Apache-DBUtils简介 com…...

保姆级教程:用HACS给追觅扫地机装Home Assistant插件,实现iPhone家庭App远程分区清扫

零门槛实现追觅扫地机HomeKit分区控制&#xff1a;HACS插件全流程指南 在智能家居生态中&#xff0c;苹果HomeKit以其出色的隐私保护和流畅的跨设备联动体验&#xff0c;成为许多iPhone用户的首选。但对于使用追觅X10/X20等型号扫地机的用户来说&#xff0c;官方App并未提供与…...

YOLOv5-6.1单通道图像训练实战:从代码修改到ONNX模型转换全解析

1. 为什么需要单通道图像训练&#xff1f; 在工业视觉和医学影像领域&#xff0c;我们经常会遇到单通道图像数据。比如X光片、红外热成像图、工业CT扫描结果等&#xff0c;这些图像通常都是灰度图&#xff0c;只包含亮度信息而没有颜色信息。传统的YOLOv5默认处理的是三通道RGB…...

C++-练习-109

题目&#xff1a;对Tv和Remote类进行如下修改a.让它们互为友元b.在Remote类中添加一个状态变量成员&#xff0c;该成员描述遥控器使处于常规状态还是互动模式c.在Remote中添加一个显式模式的方法d.在Tv类中添加一个对Remote中新成员进行切换的方法&#xff0c;该方法仅当Tv处于…...

Qt C++ 集成 SQLite 实现本地数据持久化:从原理到宠物投喂器实战

1. 项目概述与核心需求解析最近在做一个宠物智能投喂器的数据管理后台&#xff0c;核心需求是把设备上传的各种运行数据持久化存储起来&#xff0c;方便后续分析和查看。设备会上传投喂间隔时间、水温、剩余重量这几个关键参数&#xff0c;我需要一个轻量、可靠且易于集成的本地…...

告别手动排版:用docx2tex将Word文档智能转换为LaTeX

告别手动排版&#xff1a;用docx2tex将Word文档智能转换为LaTeX 【免费下载链接】docx2tex Converts Microsoft Word docx to LaTeX 项目地址: https://gitcode.com/gh_mirrors/do/docx2tex 还在为论文排版而烦恼吗&#xff1f;每次从Word转换到LaTeX都要重新调整公式、…...

3.1 FiRa UCI规范解析——命令、响应与通知的交互逻辑

1. FiRa UCI规范的核心交互机制 第一次接触FiRa UCI规范时&#xff0c;我被它严谨的消息交互设计所震撼。这个看似简单的命令-响应机制&#xff0c;实际上蕴含着UWB通信的精妙控制逻辑。就像交通信号灯指挥车辆通行一样&#xff0c;UCI规范通过明确的指令流向和状态反馈&#…...

Ubuntu 22.04 下 Nsight System/Compute 2023.3 保姆级安装与权限配置指南(解决libxcb/perf_event报错)

Ubuntu 22.04 下 Nsight System/Compute 2023.3 保姆级安装与权限配置指南 在深度学习与高性能计算领域&#xff0c;NVIDIA的Nsight工具套件是开发者不可或缺的性能分析利器。本文将手把手带你完成Ubuntu 22.04系统上最新版Nsight System 2023.3和Nsight Compute 2023.2的完整…...

碧蓝航线Alas脚本:解放双手的终极自动化解决方案

碧蓝航线Alas脚本&#xff1a;解放双手的终极自动化解决方案 【免费下载链接】AzurLaneAutoScript Azur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研&#xff0c;全自动大世界 项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAutoScript 你是否厌倦了每…...

告别盲目添加LOCAL_LDFLAGS:深入理解Android NDK链接错误与libutils的正确引用姿势

深入解析Android NDK链接错误&#xff1a;从libutils引用看系统库的正确使用姿势 当你在Android NDK开发中遇到undefined symbol错误时&#xff0c;第一反应可能是寻找快速解决方案。网上常见的建议是添加-Wl,--unresolved-symbolsignore-all来绕过链接器检查&#xff0c;但这就…...

避坑指南:Houdini风格化树木导入Unity URP后,光照和裁剪效果不对怎么办?

Houdini风格化树木在Unity URP中的渲染问题深度解析与实战修复 当你在Houdini中精心雕琢的风格化树木模型导入Unity URP管线后&#xff0c;可能会遭遇一系列令人沮丧的渲染问题&#xff1a;叶片边缘出现锯齿状裁剪、光照效果与预期不符、阴影投射异常等。这些问题的根源往往在于…...