浅谈React中的ref和useRef

news2024/12/22 23:00:19

目录

什么是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 value
    const value = refObj.current

    // updating the referenced object’s value
   refObj.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 value
   const textValue = elementRef.current.value


   // update the input element value
   elementRef.current.value = “Hello World”
}

在上面的代码片段中,我们创建了一个函数,该函数获取输入元素的当前值并将其分配给 textValue。我们还将输入元素的值更新为“Hello World”。

Ref和useRef之间的区别

既然我们了解了useRefRef工作方式及它们的差异,让我们看看如何在实际应用程序中使用它们。例如,我们希望为弹出窗口实现一个点击离开事件侦听器。我们可以利用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 functions
 return (
       {//.. 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,以及它们的使用有了一定的了解。refuseRef两者都很容易被滥用,会造成使用开销比较大。现在你可能需要考虑的是何时使用,以及如何尽可能避免使用。

以下是参考的一些用途:

  • 与输入元素交互:通过使用 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 钩子。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从0到1开发go-tcp框架【3-读写协程分离、引入消息队列、进入连接管理器、引入连接属性】【基础篇完结】

从0到1开发go-tcp框架【3-读写协程分离、引入消息队列、进入连接管理器、引入连接属性】 1 读写协程分离[v0.7] 添加一个Reader和Writer之间通信的channel添加一个Writer goroutineReader由之前直接发送给客户端改为发送给通信channel启动Reader和Writer一起工作 zinx/znet/co…

TPlink DDNS 内网穿透?外网访问设置方法

有很多小伙伴都想知道&#xff1a;TPlink路由器怎么设置DDNS内网穿透&#xff1f;今天&#xff0c;小编就给大家分享一下TPlink DDNS 外网访问设置方法&#xff0c;下面是图文教程&#xff0c;帮助新手快速入门DDNS设置。 本文介绍的是云路由器TP-LINK DDNS的设置方法。TP-LIN…

【算法提高:动态规划】1.6 区间DP

文章目录 前言例题列表1068. 环形石子合并&#xff08;前缀和 区间DP 环形转换成线性⭐&#xff09;如何把环转换成区间&#xff1f;⭐实现代码补充&#xff1a;相关题目——282. 石子合并 320. 能量项链&#xff08;另一种计算价值的石子合并&#xff09;479. 加分二叉树&am…

企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图 tbms

&#xfeff; 项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&am…

VBA技术资料MF38:VBA_在Excel中隐藏公式

【分享成果&#xff0c;随喜正能量】佛祖也无能为力的四件事&#xff1a;第一&#xff0c;因果不可改&#xff0c;自因自果&#xff0c;别人是代替不了的&#xff1b;第二&#xff0c;智慧不可赐&#xff0c;任何人要开智慧&#xff0c;离不开自身的磨练&#xff1b;第三&#…

Stable Diffusion - SDXL 1.0 全部样式设计与艺术家风格的配置与提示词

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132072482 来源于 Anna Dittmann 安娜迪特曼&#xff0c;艺术家风格的图像&#xff0c;融合幻想、数字艺术、纹理等样式。 SDXL 是 Stable Diffus…

星戈瑞 | DSPE-PEG-CY3在生物医学研究中的作用

DSPE-PEG-CY3纳米颗粒在生物医学研究中具有多种重要作用&#xff0c;主要包括以下方面&#xff1a; 1. 荧光成像&#xff1a; DSPE-PEG-CY3纳米颗粒具有花菁染料CY3的荧光特性&#xff0c;可以被用作生物标记物&#xff0c;在细胞和生物体内进行荧光成像。这种荧光成像技术可以…

基于fpga_EP4CE6F17C8_秒表计数器

文章目录 前言实验手册一、实验目的二、实验原理1&#xff0e;理论原理2&#xff0e;硬件原理 三、系统架构设计四、模块说明1&#xff0e;模块端口信号列表dig_driver(数码管驱动模块)key(按键消抖模块)top(顶层模块) 2&#xff0e;状态转移图3&#xff0e;时序图五、仿真波形…

iOS数字转为图片

根据数字&#xff0c;转成对应的图片 - (void)viewDidLoad {[super viewDidLoad];[self testNum2String:10086]; }/// 根据数字&#xff0c;显示对应的图片 数字用特定的图片显示 - (void)testNum2String:(NSInteger)num {UIView *numContentView [[UIView alloc] initWithFr…

多分支git合并流程

阅读摘要 推荐一个git合并步骤,开发分支可能会多次提交合并到dev/master主干分支也会显示很多个提交点,这样不方便代码分支管理和回溯发布记录,所以推荐如下方法,不出意外,这也是个新手教程 git 合并步骤 本地开发分支建立格式建议 feature_功能_开始时间(示例 feature_test_…

Java枚举解析:掌握枚举的绝佳指南!

申明&#xff1a;本人于公众号Java筑基期&#xff0c;CSDN先后发当前文章&#xff0c;标明原创&#xff0c;转载二次发文请注明转载公众号&#xff0c;另外请不要再标原创 &#xff0c;注意违规 枚举 在Java中&#xff0c;枚举&#xff08;Enumeration&#xff09;是一种特殊的…

MES管理系统解决方案,助力汽配行业打造数字化工厂

汽配企业的生产与供应链体系必须与整车厂协同&#xff0c;才能确保品质和交期的要求。随着竞争的加剧&#xff0c;车企不断追求更精益化的管理&#xff0c;以应对市场挑战&#xff0c;而高端客户对品质、成本、交期也提出了更高的要求。因此&#xff0c;以合理的价格提供最佳质…

Kubernetes架构和工作流程

目录 一、kubernetes简介 1.k8s的由来 2.为什么用 k8s &#xff1f; 3.k8s主要功能 二、k8s集群架构与组件 1.Master 组件 1.1Kube-apiserver 1.2Kube-controller-manager 1.3Kube-scheduler 2.Node组件 2.1Kubelet 2.2Kube-Proxy 2.3docker 或 rocket 3.配置存储中…

C++中数据的输入输出介绍

C中数据的输入输出介绍 C中数据的输入输出涉及到的文件 <iostream>&#xff1a;这是C标准库中最常用的头文件之一&#xff0c;包含了进行标准输入输出操作的类和对象&#xff0c;如std::cin、std::cout、std::endl等。 <iomanip>&#xff1a;该头文件提供了一些用…

算法与数据结构(五)--树【1】树与二叉树是什么

一.树的定义 树是一个具有层次结构的集合&#xff0c;是由一个有限集和集合上定义的一种层次结构关系构成的。不同于线性表&#xff0c;树并不是线性的&#xff0c;而是有分支的。 树&#xff08;Tree&#xff09;是n&#xff08;n>0&#xff09;个结点的有限集。 若n0&…

改变C++中私有变量成员的值

1、没有引用的情况&#xff1a; #include <iostream> #include <queue> using namespace std; class Person { public:queue<int>que; public:queue<int> getQueue(){return que;}void push(int a){que.push(a);}void pop(){que.pop();} };int main()…

RS232自由转Profinet网关扫码枪连接电脑操作

你是否曾经遇到过这样的问题&#xff1a;如何在不编写复杂代码的情况下&#xff0c;将条形码数据上传到PLC&#xff1f;今天&#xff0c;我们将为你揭示一个简单的解决方案&#xff01; 让我们来看看这个神奇的组合&#xff1a;捷米的JM-RS485/232-PN (rs232转Profient网关)和…

背景图片及精灵图

.picture {width: 48px;height: 48px;background-image: url(../images/精灵图-侧边功能.png); }为一个有宽高的div设置了背景图片&#xff0c;背景图片只作用在div的content区域内&#xff0c;不作用在padding和border上。 知识点&#xff1a; 背景图使用精灵图&#xff08;…

13-5_Qt 5.9 C++开发指南_基于信号量的线程同步_Semaphore

文章目录 1. 信号量的原理2. 双缓冲区数据采集和读取线程类设计3. QThreadDAQ和QThreadShow 的使用4. 源码4.1 可视化UI设计框架4.2 qmythread.h4.3 qmythread.cpp4.4 dialog.h4.5 dialog.cpp 1. 信号量的原理 信号量(Semaphore)是另一种限制对共享资源进行访问的线程同步机制…

2023年8月美团外卖3-18元红包优惠券天天领取活动日历及美团外卖红包领取使用

2023年8月美团外卖3-18元红包天天领取活动日历 根据上图美团外卖红包领取活动时间表以下时间可以天天领取3-18元美团外卖红包优惠券&#xff1a; 1、2023年8月18日 可领取美团外卖18元神券节红包&#xff1b; 2、2023年8月每周六、周日每天可领取12元美团外卖节红包&#xff…