浅谈React中的ref和useRef
目录
什么是useRef?
使用 ref 访问 DOM 元素
Ref和useRef之间的区别
Ref和useRef的使用案例
善用工具
结论
在各种 JavaScript
库和框架中,React
因其开发人员友好性和支持性而得到认可。
大多数开发人员发现 React
非常舒适且可扩展,因为它提供了钩子。钩子是 React
附带的内置 API,允许开发人员与 React
的状态和生命周期功能进行交互。钩子在类内部不起作用,因此它们只能在功能组件中使用。开发人员还可以决定创建自定义钩子。
React
比大多数 UI 库更能让你重新思考设计标准,允许开发人员自定义UI组件,例如使用 React
和 JSX
的抽象机制而不是典型的 DOM 规范创建视图。
在本文中,我们将讨论 React钩子函数 useRef
,使用 ref
访问 DOM 以及 ref
和 useRef
之间的区别。
什么是useRef?
React 中包含的各种钩子之一是 useRef
钩子;它用于引用功能组件中的对象,并在重新渲染之间保留引用对象的状态。
useRef
有一个名为“current
”的属性,用于随时检索引用对象的值,同时还接受初始值作为参数。您可以通过更新 current
值来更改引用对象的值。
以下是创建引用对象的方法:
import { useRef } from ‘react’const myComponent = () => {const refObj = useRef(initialValue)return (//…)
}
在上面的代码片段中,我们有一个要在应用程序中引用的对象 refObj
,要访问值或更新值,我们可以像这样调用 current
该属性:
// inside a function
const handleRefUpdate = () => {// accessing the referenced object’s valueconst value = refObj.current// updating the referenced object’s valuerefObj.current = newValue
}
您应该注意:
-
引用对象的值在重新渲染之间保持不变。
-
更新引用对象的值不会触发重新呈现。
使用 ref 访问 DOM 元素
请记住,DOM
元素也是对象,我们可以使用useRef
引用它们。但是现在,我们需要利用另一个名为 ref
。
ref
是一个 HTML
属性,它将引用的对象分配给 DOM
元素。让我们看看这是如何工作的:
import {useRef} from ‘react’const myComponent = () => {const elementRef = useRef()return (<input ref={elementRef} type=”text” />)
}
在上面的代码片段中,我们创建了一个新的引用对象,elementRef
并使用属性 ref
将其分配给输入标记。我们可以访问输入标签的值并像这样更新值:
const handleInput = () => {//accessing the input element valueconst textValue = elementRef.current.value// update the input element valueelementRef.current.value = “Hello World”
}
在上面的代码片段中,我们创建了一个函数,该函数获取输入元素的当前值并将其分配给 textValue
。我们还将输入元素的值更新为“Hello World
”。
Ref和useRef之间的区别
既然我们了解了useRef
和Ref
工作方式及它们的差异,让我们看看如何在实际应用程序中使用它们。例如,我们希望为弹出窗口实现一个点击离开事件侦听器。我们可以利用ref
访问弹出窗口的 DOM 元素,并在弹出窗口外单击时进行侦听。
在你的react 应用中,你可以创建一个名为“hooks
”的文件夹,这个文件夹将包含自定义钩子。
在文件夹中创建一个新文件 useClickAway
,并在文件中输入以下代码:
import React, { useEffect} from 'react'export default function useClickAway(ref: any, callback: Function) {useEffect(() => {function handleClickAway(event: any) {if (ref.current && !ref.current.contains(event.target)) {callback();}}document.addEventListener("mousedown", handleClickAway);return () => {document.removeEventListener("mousedown", handleClickAway);};}, [ref]);};
在上面的代码片段中,我们创建了一个接受引用对象作为 ref
和回调函数的自定义钩子,然后我们执行了一个事件侦听器来检查何时单击鼠标,如果单击不在当前 ref
上,则我们触发回调函数。
以下是产品页面上自定义挂钩的实现:
import React, { useRef } from "react";
//.. Other importations
export default function Storefront() {const targetElement = useRef(null)const alertClickAway = () => {alert("Clicked outside product 1")}useClickAway(targetElement, alertClickAway)//.. Other functionsreturn ({//.. Other parts of the application}<div className="gallery"><div className="col" ref={targetElement}><img src="https://i.postimg.cc/G207QNV7/image.png" alt="Product 1" /><p>iWatch Series 6</p><div className="btns"><button><img src="https://api.iconify.design/flat-color-icons:like.svg?color=%23888888" alt="like" /></button><button><img src="https://api.iconify.design/icon-park:buy.svg?color=%23888888"alt="add" /></button></div></div>)
}
在上面的代码片段中,我们有一个店面组件,我们在其中导入了自定义钩子,然后我们创建了一个新的引用对象 targetElement
并将其分配给产品库中的 div
,然后我们创建了一个回调函数useClickAway
,以便在使用ref
在产品项外部单击鼠标时发出警报 targetElement
。
现在让我们看看输出:
Ref和useRef的使用案例
你现在对什么是ref
以及useRef
,以及它们的使用有了一定的了解。ref
和useRef
两者都很容易被滥用,会造成使用开销比较大。现在你可能需要考虑的是何时使用,以及如何尽可能避免使用。
以下是参考的一些用途:
-
与输入元素交互:通过使用
refs
可以访问输入元素并执行焦点、更改跟踪或自动完成等功能。 -
与第三方 UI 库交互:
ref
可用于与第三方 UI 库创建的元素进行交互,这些元素使用标准 DOM 方法访问可能很棘手。例如,如果您使用第三方库生成滑块,则可以使用ref
访问滑块的 DOM 元素,而无需被告知滑块库源代码的结构。 -
媒体播放:您还可以使用
refs
访问图像、音频或视频等媒体资产,并与它们的呈现方式进行交互。例如,当元素进入视口时自动播放视频或延迟加载图像。 -
复杂动画触发:传统上,
CSS
关键帧或超时用于确定何时启动动画。在某些情况下(可能更复杂),您可以使用refs
来观察 DOM 元素并确定何时开始动画。
在某些情况下(如下所示),不应使用引用:
-
声明性案例:即使在使用
refs
的简单解决方案的情况下,也无需编写更昂贵的代码来执行相同的任务。例如,使用条件渲染来隐藏或显示 DOM 元素而不是ref
。 -
影响状态的元素:有时,使用
refs
的概念非常有趣,以至于您忽略了对元素所做的修改对应用程序生命周期的影响。您应该记住,对ref
的更改不会导致重新渲染,并且ref
在渲染中保持其对象的值。因此,建议避免在状态更改需要触发重新渲染的情况下使用ref
。 -
访问功能组件:不应被误认为功能组件的 DOM 元素可以使用
Ref
属性进行引用。因为,与类组件或 DOM 元素不同,功能组件没有实例。例如:
import {useRef} from ‘react’const FunctionalComponent = () => {return (<h1>Hello World<>
)
}const myComponent = () => {const elementRef = useRef()return (<FunctionalComponent ref={elementRef} />)
}
由于组件 FunctionalComponent
没有实例,因此上述代码片段中的 ref
将不起作用。相反,我们可以将其转换为FunctionalComponent
类组件或在 FunctionalComponent
组件的 forwardRef
中使用。
善用工具
成功的前端工程师很会善用工具,这些年低代码概念开始流行,像国外的 Mendix,国内的 JNPF,这种新型的开发方式,图形化的拖拉拽配置界面,并兼容了自定义的组件、代码扩展,确实在 B 端后台管理类网站建设中很大程度上的提升了效率。
开源地址:JNPF体验中心
代码量少,系统的稳定性和易调整性都会得到一定的保障。基于代码生成器,可一站式开发多端使用 Web、Android、IOS、微信小程序。代码自动生成后可以下载本地,进行二次开发,有效提高整体开发效率。同时,支持多种云环境部署、本地部署给予最大的安全保障,可以快速搭建适合自身应用场景的产品。
结论
在本文中,我们讨论了如何使用 useRef
钩子创建引用,该钩子采用初始值并修改引用对象的“current
”属性的值以更新其值。
我们看到了如何将“current
”值与“ref
”一起使用来访问 DOM 元素并与其属互。
我们将介绍如何创建一个接受引用 DOM 元素的自定义钩子和一个回调函数,以便在应用程序中使用 “ref
” 和 “useRef
” 来观察 DOM 元素上的单击事件。
此外,我们还讨论了“ref
”和“useRef
”的用例,何时使用它们,何时不使用它们。
在了解了ref
以及useRef
如何在不重新渲染父组件的情况下跟踪和更新可变值之后,您可以通过查看Refs
和 useRefs
的 React
的相关官方文档,来探索更多关于它们的信息或了解更多信息,甚至尝试其他 React
钩子。
相关文章:

浅谈React中的ref和useRef
目录 什么是useRef? 使用 ref 访问 DOM 元素 Ref和useRef之间的区别 Ref和useRef的使用案例 善用工具 结论 在各种 JavaScript 库和框架中,React 因其开发人员友好性和支持性而得到认可。 大多数开发人员发现 React 非常舒适且可扩展,…...

Linux C 获取主机网卡名及 IP 的几种方法
在进行 Linux 网络编程时,经常会需要获取本机 IP 地址,除了常规的读取配置文件外,本文罗列几种个人所知的编程常用方法,仅供参考,如有错误请指出。 方法一:使用 ioctl() 获取本地 IP 地址 Linux 下可以使用…...

解密外接显卡:笔记本能否接外置显卡?如何连接外接显卡?
伴随着电脑游戏和图形处理的需求不断增加,很多笔记本电脑使用者开始考虑是否能够通过外接显卡来提升性能。然而,外接显卡对于笔记本电脑是否可行,以及如何连接外接显卡,对于很多人来说仍然是一个迷。本文将为您揭秘外接显卡的奥秘…...

list与erase()
运行代码: //list与erase() #include"std_lib_facilities.h" //声明Item类 struct Item {string name;int iid;double value;Item():name(" "),iid(0),value(0.0){}Item(string ss,int ii,double vv):name(ss),iid(ii),value(vv){}friend istr…...

Arcgis 分区统计majority参数统计问题
利用Arcgis 进行分区统计时,需要统计不同矢量区域中栅格数据的众数(majority),出现无法统计majority参数问题解决 解决:利用copy raster工具,将原始栅格数据 64bit转为16bit...

vue2+wangEditor5富文本编辑器(图片视频自定义上传七牛云/服务器)
1、安装使用 安装 yarn add wangeditor/editor # 或者 npm install wangeditor/editor --save yarn add wangeditor/editor-for-vue # 或者 npm install wangeditor/editor-for-vue --save在main.js中引入样式 import wangeditor/editor/dist/css/style.css在使用编辑器的页…...

shell脚本练习--安全封堵脚本,使用firewalld实现
一.什么是安全封堵 安全封堵(security hardening)是指采取一系列措施来增强系统的安全性,防止潜在的攻击和漏洞利用。以下是一些常见的安全封堵措施: 更新和修补系统:定期更新操作系统和软件包以获取最新的安全补丁和修…...

双端冒泡排序
双端冒泡排序是对传统冒泡排序的改进,其主要改进在于同时从两端开始排序,相对于传统冒泡排序每次只从一端开始排序,这样可以减少排序的遍历次数。 传统冒泡排序从一端开始,每次将最大(或最小)的元素冒泡到…...

如何在Visual Studio Code中用Mocha对TypeScript进行测试
目录 使用TypeScript编写测试用例 在Visual Studio Code中使用调试器在线调试代码 首先,本文不是一篇介绍有关TypeScript、JavaScript或其它编程语言数据结构和算法的文章。如果你正在准备一场面试,或者学习某一个课程,互联网上可以找到许多…...

GO中Json的解析
一个json字串,想要拿到其中的数据,就需要解析出来 一、适用于json数据的结构已知的情况下 使用json.Unmarshal将json数据解析到结构体中 根据json字串数据的格式定义struct,用来保存解码后的值。这里首先定义了一个与要解析的数据结构一样的…...

chatgpt 提示词-关于数据科学的 75个词语
这里有 75 个 chatgpt 提示,可以立即将其用于数据科学或数据分析等。 1. 伪装成一个SQL终端 提示:假设您是示例数据库前的 SQL 终端。该数据库包含名为“用户”、“项目”、“订单”、“评级”的表。我将输入查询,您将用终端显示的内容进行…...

(自控原理)控制系统的数学模型
目录 一、时域数学模型 1、线性元件微分方程的建立 2、微分方程的求解方法编辑 3、非线性微分方程的线性化 二、复域数学模型 1、传递函数的定义 2、传递函数的标准形式 3、系统的典型环节的传递函数 4、传递函数的性质 5、控制系统数学模型的建立 6、由传递函数求…...

Webpack5 cacheGroups
文章目录 一、 cacheGroups是什么?二、怎么使用cacheGroups?三、cacheGroups实际应用之一? 一、 cacheGroups是什么? 在Webpack 5中,cacheGroups是用于配置代码拆分的规则,它可以帮助你更细粒度地控制生成…...

前端面试的游览器部分(5)每篇10题
41.什么是浏览器的同步和异步加载脚本的区别?你更倾向于使用哪种方式,并解释原因。 浏览器的同步和异步加载脚本是两种不同的脚本加载方式,它们的主要区别在于加载脚本时是否阻塞页面的解析和渲染。 同步加载脚本: 同步加载脚本…...

数据挖掘七种常用的方法汇总
数据挖掘(Data Mining)就是从大量的、不完全的、有噪声的、模糊的、随机的实际应用数据中,提取隐含在其中的、人们事先不知道的、但又是潜在有用的信息和知识的过程。这个定义包括几层含义:数据源必须是真实的、大量的、含噪声的;发现的是用户…...

自然语言处理学习笔记(二)————语料库与开源工具
目录 1.语料库 2.语料库建设 (1)规范制定 (2)人员培训 (3)人工标注 3.中文处理中的常见语料库 (1)中文分词语料库 (2)词性标注语料库 (3…...

Rust dyn - 动态分发 trait 对象
dyn - 动态分发 trait 对象 dyn是关键字,用于指示一个类型是动态分发(dynamic dispatch),也就是说,它是通过trait object实现的。这意味着这个类型在编译期间不确定,只有在运行时才能确定。 practice tr…...

uniapp 中过滤获得数组中某个对象里id:1的数据
// 假设studentData是包含多个学生信息的数组 const studentData [{id: 1, name: 小明, age: 18},{id: 2, name: 小红, age: 20},{id: 3, name: 小刚, age: 19},{id: 4, name: 小李, age: 22}, ]; // 过滤获取id为1的学生信息 const result studentData.filter(item > ite…...

Django系列之Channels
1. Channels 介绍 Django 中的 HTTP 请求是建立在请求和响应的简单概念之上的。浏览器发出请求,Django服务调用相应的视图函数,并返回响应内容给浏览器渲染。但是没有办法做到 服务器主动推送消息给浏览器。 因此,WebSocket 就应运而生了。…...

HTTP——五、与HTTP协作的Web服务器
HTTP 一、用单台虚拟主机实现多个域名二、通信数据转发程序 :代理、网关、隧道1、代理2、网关3、隧道 三、保存资源的缓存1、缓存的有效期限2、客户端的缓存 一台 Web 服务器可搭建多个独立域名的 Web 网站,也可作为通信路径上的中转服务器提升传输效率。…...

pyspark笔记 Timestamp 类型的比较
最近写pyspark遇到的一个小问题。 假设我们有一个pyspark DataFrame叫做dart 首先将dart里面timestamp这一列转化成Timestamp类型 dartdart.withColumn(timestamp,col(timestamp).cast(TimestampType()))查看timestamp的前5个元素 dart.select(timestamp).show(5,truncateFal…...

SpringBoot 集成 Redis
本地Java连接Redis常见问题: bind配置请注释掉保护模式设置为noLinux系统的防火墙设置redis服务器的IP地址和密码是否正确忘记写访问redis的服务端口号和auth密码 集成Jedis jedis是什么 Jedis Client是Redis官网推荐的一个面向java客户端,库文件实现…...

黑客学习笔记(网络安全)
一、首先,什么是黑客? 黑客泛指IT技术主攻渗透窃取攻击技术的电脑高手,现阶段黑客所需要掌握的远远不止这些。 以前是完全涉及黑灰产业的反派角色,现在大体指精通各种网络技术的程序人员 二、为什么要学习黑客技术?…...

[openCV]基于拟合中线的智能车巡线方案V1
import cv2 as cv import os import numpy as np# 遍历文件夹函数 def getFileList(dir, Filelist, extNone):"""获取文件夹及其子文件夹中文件列表输入 dir:文件夹根目录输入 ext: 扩展名返回: 文件路径列表"""newDir d…...

MyBatis-Plus 和达梦数据库实现高效数据持久化
一、添加依赖 首先,我们需要在项目的 pom.xml 文件中添加 MyBatis-Plus 和达梦数据库的依赖: <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifac…...

已注销【888】
元神密码 - 飞书云文档 (feishu.cn)...

Ceph错误汇总
title: “Ceph错误汇总” date: “2020-05-14” categories: - “技术” tags: - “Ceph” - “错误汇总” toc: false original: true draft: true Ceph错误汇总 1、执行ceph-deploy报错 1.1、错误信息 ➜ ceph-deploy Traceback (most recent call last):File "/us…...

DataTable过滤某些数据
要过滤DataTable中的某些数据,可以使用以下方法: 使用Select方法:可以使用DataTable的Select方法来筛选满足指定条件的数据行。该方法接受一个字符串参数作为过滤条件,返回一个符合条件的数据行数组。 DataTable filteredTable …...

JAVASE---继承和多态
继承 比如,狗和猫,它们都是一个动物,有共同的特征,我们就可以把这种特征抽取出来。 像这样把相同的可以重新放到一个类里面,进行调用,这就是继承。 概念 继承(inheritance)机制:是面向对象程…...

Centos7升级gcc、g++版本(转载)
Centos7默认的 gcc版本是 4.8.5 默认使用yum install gcc安装出来的gcc版本也是是4.8.5。 1.首先查看自己的 gcc 版本 gcc -v g -v如果出现:bash: g: 未找到命令... 则安装g:遇到暂停时,输入y继续安装 yum install gcc-c然后输入…...