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></>);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/167145.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3实现在element Dialog 对话框中预览pdf文件

最近有一个需求就是点击按钮在弹框中去预览pdf文件&#xff0c;于是发现了一个HTML中比较重要的标签&#xff1a;embed&#xff0c;前面说的需求就可以用这个标签来实现&#xff0c;一起来学习一下吧。 embed标签是HTML中的一个非常重要的标签&#xff0c;它可以在你的网页上插…

PDF编辑阅读 PDF Expert v3.5.2

PDF Expert是由Readdle开发的一款专业的PDF编辑和阅读工具。它可以帮助用户在Mac、iPad和iPhone等设备上查看、注释、编辑、填写和签署PDF文档。 以下是PDF Expert的特点&#xff1a; PDF编辑&#xff1a;PDF Expert提供了丰富的PDF编辑功能&#xff0c;包括添加、删除、移动…

linux性能分析(五)如何学习linux性能优化

一 如何学习linux性能优化 强调&#xff1a; 由于知识记忆曲线以及某些知识点不常用,所以一定要注重复习思考&#xff1a; 如何进行能力转义以及能力嫁接? --> 真正站在巨人的肩膀上性能调优的目的&#xff1a; 不影响系统稳定性的资源最大利用化补充&#xff1a; 性能…

java新特性流 stream01

案例描述 今天跟着黑马程序员的视频&#xff0c;完成“瑞吉外卖”项目的菜品信息管理模块的时候&#xff0c;遇到了一个比较陌生的写法 用到了Java8的新特性 stream().map((item) -> {}).collect() List<DishDto> collect records.stream().map((item) -> {DishDt…

【德哥说库系列】-RHEL8环境源码编译安装MySQL8.0

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

【C++】C++11新特性之右值引用与移动语义

文章目录 一、左值与左值引用二、右值与右值引用三、 左值引用与右值引用比较四、右值引用使用场景和意义1.左值引用的短板2.移动构造和移动赋值3.STL中右值引用的使用 五、万能引用与完美转发1.万能引用2.完美转发 一、左值与左值引用 在C11之前&#xff0c;我们把数据分为常…

[论文笔记]GPT-2

引言 今天继续GPT系列论文&#xff0c; 这次是Language Models are Unsupervised Multitask Learners&#xff0c;即GPT-2&#xff0c;中文题目的意思是 语言模型是无监督多任务学习器。 自然语言任务&#xff0c;比如问答、机器翻译、阅读理解和摘要&#xff0c;是在任务相关…

框架篇

一、Spring中的单例Bean是线程安全的吗 二、AOP相关面试题 三、Spring中的事务 四、Spring中事务失效的场景有 五、Spring bean的生命周期 六、Spring的循环依赖 七、SpringMVC的执行流程 八、自动配置原理 九、Spring框架常见的注解 十、Mybatis的执行流程 十一、MyBatis延迟加…

postgresql(openGauss)模糊匹配参数

被pg系这个show要求精准匹配参数恶心的不轻。 原理是用.psqlrc&#xff08;openGauss用.gsqlrc&#xff09;文件set一个select常量进去&#xff0c;需要用&#xff1a;调用这个常量。理论上也可以增强其他的各种功能。 我在openGauss做的一个例子 .gsqlrc&#xff08;.psqlrc…

自学SLAM(4)《第二讲:三维物体刚体运动》作业

前言 小编研究生的研究方向是视觉SLAM&#xff0c;目前在自学&#xff0c;本篇文章为初学高翔老师课的第二次作业。 文章目录 前言1.熟悉 Eigen 矩阵运算2.几何运算练习3.旋转的表达4.罗德里格斯公式的证明5.四元数运算性质的验证6.熟悉 C11 1.熟悉 Eigen 矩阵运算 设线性⽅程 …

分布式共识算法及落地

摘要 本文介绍常见的分布式共识算法&#xff0c;使用场景&#xff0c;以及相关已经落地了的程序或框架 1. 为什么要分布式共识算法 在分布式系统中&#xff0c;不同节点之间可能存在网络延迟、故障等原因导致彼此之间存在数据不一致的情况&#xff0c;为了保证分布式系统中的…

[TCP1P 2023] 部分crypto,pwn,reverse

Crypto Final Consensus 这是个AES爆破密钥的题&#xff0c;加密方法是先后用两个密钥加密。远程先给出加密后的flag&#xff0c;然后允许输入值并进行加密。 from Crypto.Cipher import AES import random from Crypto.Util.Padding import pada b"" b b"&…

系统架构师考试科目一:综合知识

某软件公司欲开发一个 Windows 平台上的公告板系统。在明确用户需求后&#xff0c;该公司的 架构师决定采用 Command 模式实现该系统的界面显示部分&#xff0c;并设计 UML 类图如下 图所示。图中与 Command 模式中的 Invoker 角色相对应的类是( ) &#xff0c;与 ConcreteComm…

一篇文章讲懂mysql中的锁

事务的隔离性是由锁来实现的。 为什么需要锁 锁是计算机协调多个进程或线程并发访问某一资源的机制。在程序开发中会存在多线程同步的问题&#xff0c;当多个线程并发访问某个数据的时候&#xff0c;尤其是针对一些敏感的数据&#xff08;比如订单、金额等&#xff09;&#x…

C语言 ——宽字符

前言&#xff1a; 过去C语⾔并不适合⾮英语国家&#xff08;地区&#xff09;使⽤。 C语⾔最初假定字符都是单字节的。但是这些假定并不是在世界的任何地⽅都适⽤。 C语⾔字符默认是采⽤ASCII编码的&#xff0c;ASCII字符集采⽤的是单字节编码&#xff0c;且只使⽤了单字节中…

Opensuse Tumbleweed快速部署K8S-1.28.2

** #查看你的网卡信息 nmcli device show#设置你的静态IP nmcli connection modify ens32 ipv4.method manual \ipv4.addresses 172.16.20.214/24 ipv4.gateway 172.16.20.1 \ipv4.dns 114.114.114.114#重启网卡生效 nmcli c down ens32 && nmcli c up ens32#添加DNS …

代码随想录算法训练营第二十九天 | 回溯算法总结

​ 代码随想录算法训练营第二十九天 | 回溯算法总结 1. 组合问题 1.1 组合问题 在77. 组合中&#xff0c;我们开始用回溯法解决第一道题目&#xff1a;组合问题。 回溯算法跟k层for循环同样是暴力解法&#xff0c;为什么用回溯呢&#xff1f;回溯法的魅力&#xff0c;用递…

解决appium或selenium使用时driver.find_element_by_xpath中间有删除线问题

一、问题描述 Darren洋在公司电脑搭建完成appium后准备运行appium2.0版本执行脚本时发现执行脚本中的driver.find_element_by_xpath中间有删除线&#xff0c;说明较高版本的appium及selenium中该方法已被弃用。 二、解决办法 该问题解决办法为将driver.find_element_by_xpath()…

Linux线程--创建及等待

1.进程与线程 典型的UNIX/Linux进程可以看成只有一个控制线程&#xff1a;一个进程在同一时刻只做一件事情。有了多个控制线程后&#xff0c;在程序设计时可以把进程设计成在同一时刻做不止一件事&#xff0c;每个线程各自处理独立的任务。  线程是操作系统能够进行运算调度的…