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

react 学习 —— 16、使用 ref 操作 DOM

什么时候使用 ref 操作 DOM?

有时你可能需要访问由 React 管理的 DOM 元素 —— 例如,让一个节点获得焦点、滚动到它或测量它的尺寸和位置。在 React 中没有内置的方法来做这些事情,所以你需要一个指向 DOM 节点的 ref 来实现。

怎么使用 ref 操作 DOM?

首先,引入 useRef Hook:

import { useRef } from 'react';

然后,在你的组件中使用它声明一个 ref:

const myRef = useRef(null);

最后,将你的 ref 作为 ref 属性传递给你想要获得 DOM 节点的 JSX 标签:

<div ref={myRef}>

useRef Hook 返回一个对象,该对象有一个名为 current 的属性。最初,myRef.current 是 null。当 React 为这个 <div /> 创建一个 DOM 节点时,React 会把对该节点的引用放入 myRef.current。然后,你可以从 事件处理器 访问此 DOM 节点,并使用在其上定义的内置浏览器 API。

myRef.current.scrollIntoView();

如何使用 ref 回调管理 ref 列表?

有时候,你可能需要为列表中的每一项都绑定 ref ,而你又不知道会有多少项。像下面这样做是行不通的:

<ul>{items.map((item) => {// 行不通!const ref = useRef(null);return <li ref={ref} />;})}
</ul>

这是因为 Hook 只能在组件的顶层被调用。不能在循环语句、条件语句或 map() 函数中调用 useRef 。
一种可能的解决方案是用一个 ref 引用其父元素,然后用 DOM 操作方法如 querySelectorAll 来寻找它的子节点。然而,这种方法很脆弱,如果 DOM 结构发生变化,可能会失效或报错。
另一种解决方案是将函数传递给 ref 属性。这称为 ref 回调。当需要设置 ref 时,React 将传入 DOM 节点来调用你的 ref 回调,并在需要清除它时传入 null 。这使你可以维护自己的数组或 Map,并通过其索引或某种类型的 ID 访问任何 ref。

import { useRef } from 'react';export default function CatFriends() {const itemsRef = useRef(null);function scrollToId(itemId) {const map = getMap();const node = map.get(itemId);node.scrollIntoView({behavior: 'smooth',block: 'nearest',inline: 'center'});}function getMap() {if (!itemsRef.current) {// 首次运行时初始化 Map。itemsRef.current = new Map();}return itemsRef.current;}return (<><nav><button onClick={() => scrollToId(0)}>Tom</button><button onClick={() => scrollToId(5)}>Maru</button><button onClick={() => scrollToId(9)}>Jellylorum</button></nav><div><ul>{catList.map(cat => (<likey={cat.id}ref={(node) => {const map = getMap();if (node) {map.set(cat.id, node);} else {map.delete(cat.id);}}}><imgsrc={cat.imageUrl}alt={'Cat #' + cat.id}/></li>))}</ul></div></>);
}const catList = [];
for (let i = 0; i < 10; i++) {catList.push({id: i,imageUrl: 'https://placekitten.com/250/200?image=' + i});
}

怎样访问另一个组件的 DOM 节点?

当你将 ref 放在像 这样输出浏览器元素的内置组件上时,React 会将该 ref 的 current 属性设置为相应的 DOM 节点(例如浏览器中实际的 )。
但是,如果你尝试将 ref 放在 你自己的 组件上,例如 ,默认情况下你会得到 null。

import { useRef } from 'react';function MyInput(props) {return <input {...props} />;
}export default function MyForm() {const inputRef = useRef(null);function handleClick() {inputRef.current.focus();}return (<><MyInput ref={inputRef} /><button onClick={handleClick}>聚焦输入框</button></>);
}

为了帮助您注意到这个问题,React 还会向控制台打印一条错误消息:
在这里插入图片描述
发生这种情况是因为默认情况下,React 不允许组件访问其他组件的 DOM 节点。甚至自己的子组件也不行!这是故意的。Refs 是一个应急方案,应该谨慎使用。手动操作 另一个 组件的 DOM 节点会使你的代码更加脆弱。

相反,想要 暴露其 DOM 节点的组件必须选择该行为。一个组件可以指定将它的 ref “转发”给一个子组件。下面是 MyInput 如何使用 forwardRef API:

import { forwardRef, useRef } from 'react';const MyInput = forwardRef((props, ref) => {return <input {...props} ref={ref} />;
});export default function Form() {const inputRef = useRef(null);function handleClick() {inputRef.current.focus();}return (<><MyInput ref={inputRef} /><button onClick={handleClick}>聚焦输入框</button></>);
}

相关文章:

react 学习 —— 16、使用 ref 操作 DOM

什么时候使用 ref 操作 DOM&#xff1f; 有时你可能需要访问由 React 管理的 DOM 元素 —— 例如&#xff0c;让一个节点获得焦点、滚动到它或测量它的尺寸和位置。在 React 中没有内置的方法来做这些事情&#xff0c;所以你需要一个指向 DOM 节点的 ref 来实现。 怎么使用 r…...

Qt planeGame day10

Qt planeGame day10 Game基本框架 qt中没有现成的游戏框架可以用&#xff0c;我们需要自己搭框架首先创建一个QGame类作为框架&#xff0c;这个基本框架里面应该有如下功能&#xff1a;游戏初始化 void init(const QSize& siez,const QString& title);游戏反初始化(…...

贪吃蛇项目实践

游戏背景&#xff1a; 贪吃蛇是久负盛名的游戏&#xff0c;它也和俄罗斯⽅块&#xff0c;扫雷等游戏位列经典游戏的⾏列。 实现基本的功能&#xff1a; 贪吃蛇地图绘制 蛇吃⻝物的功能 &#xff08;上、下、左、右⽅向键控制蛇的动作&#xff09; 蛇撞墙死亡 蛇撞⾃⾝死亡 计…...

【C++】哈希应用——海量数据面试题

哈希应用——海量数据面试题 一、位图应用1、给定100亿个整数&#xff0c;设计算法找到只出现一次的整数&#xff1f;2、给两个文件&#xff0c;分别有100亿个整数&#xff0c;我们只有1G内存&#xff0c;如何找到两个文件交集&#xff1f;&#xff08;1&#xff09;用一个位图…...

​CUDA学习笔记(五)GPU架构

本篇博文转载于https://www.cnblogs.com/1024incn/tag/CUDA/&#xff0c;仅用于学习。 GPU架构 SM&#xff08;Streaming Multiprocessors&#xff09;是GPU架构中非常重要的部分&#xff0c;GPU硬件的并行性就是由SM决定的。 以Fermi架构为例&#xff0c;其包含以下主要组成…...

逻辑漏洞详解

原理&#xff1a; 没有固定的概念&#xff0c;一般都是不符合常识的情况。比如任意用户注册&#xff0c;短信炸弹&#xff0c;占用资源&#xff0c;交易支付、密码修改、密码找回、越权修改、越权查询、突破限制。 根据实际业务逻辑进行比对&#xff0c;购物的可以根据数量&a…...

MySQL——八、MySQL索引视图

MySQL 一、视图1、什么是视图2、为什么需要视图3、视图的作用和优点4、创建视图5、视图使用规则6、修改视图7、删除视图 二、索引1、什么是索引2、索引优缺点3、索引分类4、索引的设计原则5、创建索引5.1 创建表是创建索引5.2 create index5.3 ALTER TABLE 6、删除索引7、MySQL…...

力扣100097. 合法分组的最少组数(哈希+贪心)

题目描述&#xff1a; 给你一个长度为 n 下标从 0 开始的整数数组 nums 。 我们想将下标进行分组&#xff0c;使得 [0, n - 1] 内所有下标 i 都 恰好 被分到其中一组。 如果以下条件成立&#xff0c;我们说这个分组方案是合法的&#xff1a; 对于每个组 g &#xff0c;同一…...

uniapp map地图实现marker聚合点,并点击marker触发事件

1.uniapp官方文档说明 2.关键代码片段 // 仅调用初始化&#xff0c;才会触发 on.("markerClusterCreate", (e) > {})this._mapContext.initMarkerCluster({enableDefaultStyle: false, // 是否使用默认样式zoomOnClick: true, // 点击聚合的点&#xff0c;是否…...

【Mysql】Mysql中的B+树索引(六)

概述 从上一章节我们了解到InnoDB 的数据页都是由7个部分组成&#xff0c;然后各个数据页之间可以组成一个双向链表 &#xff0c;而每个数据页中的记录会按照主键值从小到大的顺序组成一个单向链表 &#xff0c;每个数据页都会为存储在它里边儿的记录生成一个页目录 &#xff…...

【Dockerfile镜像实战】构建LNMP环境并运行Wordpress网站平台

这里写目录标题 一、项目背景和要求二、项目环境三、部署过程1&#xff09;创建自定义网络2&#xff09;部署NginxStep1 创建工作目录并上传相关软件包Step2 编写Dockerfile文件Step3 编写配置文件nginx.confStep4 创建nginx镜像Step5 运行容器 3&#xff09;部署MysqlStep1 创…...

【工具】利用ffmpeg将网页中的.m3u8视频文件转化为.mp4格式

目录 0.环境 1.背景 2.前提 3.详细描述 1&#xff09;在网站上找到你想下载的视频的.m3u8链接 2&#xff09;打开命令行&#xff0c;用ffmpeg命令进行转化 3&#xff09;过程&结果截图 0.环境 windows64 ffmpeg 1.背景 网页上有个.m3u8格式的视频文件&#xff0c;…...

Git简洁安装方式和使用方式【附安装包资源,Git基础操作,如拉取项目、上传代码、拉取代码】

文章目录 软件安装包安装步骤常用使用方式注意拉取项目上传代码或文件选择文件添加到本地Git存储库的缓存区将缓存区的更改提交到本地Git存储库&#xff0c;并设置提交信息将本地Git存储库的更新推送到远程Git仓库中上传示例拉取别人所上传的代码 常见问题上传代码失败&#xf…...

【29】c++设计模式——>策略模式

策略模式 C中的策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许在运行时选择算法的行为。策略模式通过将算法封装成独立的类&#xff0c;并且使它们可以互相替换&#xff0c;从而使得算法的变化独立于使用算法的客户端。 策略模式通…...

2023Jenkins连接k8s

首先配置k8s config文件 1.方式获取k8s密钥 cat .kube/config 2.导出方式或者密钥 kubectl config view --raw > k8s-config-admin pipeline {agent {kubernetes {yaml apiVersion: v1kind: Podmetadata:labels:some-label: devopsspec:containers:- name: dockerimage: d…...

SpringBoot 入门 参数接收 必传参数 数组 集合 时间接收

接口声明 RestController //表示该类为请求处理类public class HttpDeal {RequestMapping("/login")//这个方法处理哪一个地址过来的请求public String hello(){return "返回给浏览器";}}接收参数 RequestMapping("/login")public String logi…...

【Qt之JSON文件】QJsonDocument、QJsonObject、QJsonArray等类介绍及使用

Qt之JSON相关类介绍 QJsonDocument常用函数枚举类型 QJsonDocument::DataValidation枚举类型 QJsonDocument::JsonFormat构造函数静态函数成员函数示例 QJsonObject常用函数构造函数&#xff1a;成员函数&#xff1a; QJsonObject 与 QVariantMap 相互转换 QJsonArray常用函数构…...

阿里云今年有双十一活动吗?不好说

阿里云今年有双十一活动吗&#xff1f;不好说&#xff0c;因为去年就没有。阿里云双11优惠活动是一项大型的促销活动&#xff0c;每年都有&#xff0c;但是去年没有双十一活动&#xff0c;不知道今年2023年阿里云是否有双11优惠活动。但是阿里云百科aliyunbaike.com猜想&#x…...

【驱动开发】创建设备节点、ioctl函数的使用

一、控制三盏灯的亮灭 头文件&#xff1a; #ifndef __HEAD_H__ #define __HEAD_H__ typedef struct{unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int ODR; }gpio_t; #define PHY_LED1_ADDR 0X50006000 #def…...

Tomcat启动控制台乱码问题

修改Tomcat/conf/logging.properties...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...