React 中ref的三种形式

引言💭

在 React 中,ref 是一个重要的功能,用于直接访问 DOM 元素或组件实例。通常,我们使用 ref 来实现一些需要直接操作 DOM 的场景,例如焦点管理、文本选择或动画等。

在 React 中,ref 主要有三种形式:字符串形式、回调形式和 createRef。

一、字符串形式的 ref(不推荐使用)

ref 可以使用字符串形式来引用 DOM 元素或组件实例,如下所示:

scala 复制代码
class MyComponent extends React.Component {
  render() {
    return <div ref="myDiv">Hello</div>;
  }

  componentDidMount() {
    console.log(this.refs.myDiv);  // 通过 refs 获取 DOM 元素
  }
}

在组件挂载后,React 会在 refs 对象中自动为每个字符串形式的 ref 创建一个属性,指向对应的 DOM 元素或组件实例。

使用场景

  • 字符串形式的 ref 在早期版本中常用于引用 DOM 元素,尤其是对于较简单的组件而言。
  • 然而,其缺乏灵活性,且容易导致潜在的性能问题和调试困难。因此,开发者应避免使用字符串形式的 ref。

二、回调形式的 ref

类方法中的回调 ref

在 React 中,回调形式的 ref 是通过将一个函数传递给 ref 属性来动态设置引用的方式。这个函数会在组件挂载时被调用,并将对应的 DOM 元素或组件实例作为参数传递给它。这个方式通常用于需要在组件生命周期的特定时刻访问 DOM 或组件实例的情况。

scala 复制代码
class MyComponent extends React.Component {
  setRef = (element) => {
    this.myDiv = element;  // 获取 DOM 元素
  };

  render() {
    return <div ref={this.setRef}>Hello</div>;
  }

  componentDidMount() {
    console.log(this.myDiv);  // 通过 this.myDiv 获取 DOM 元素
  }
}

在这个例子中,ref={this.setRef} 将 setRef 方法作为回调函数传递。当组件挂载时,React 会调用 setRef 函数,并将 DOM 元素作为参数传入。这样,this.myDiv 就能引用到挂载的 DOM 元素。

内联回调函数

除了使用类方法来定义回调函数,你还可以将回调函数直接写成内联函数,进一步简化代码。这种写法特别适用于一些简单的场景,避免了额外定义方法。

scala 复制代码
class MyComponent extends React.Component {
  render() {
    return <div ref={(element) => { this.myDiv = element; }}>Hello</div>;
  }

  componentDidMount() {
    console.log(this.myDiv);  // 通过 this.myDiv 获取 DOM 元素
  }
}

在这个例子中,ref={(element) => { this.myDiv = element; }} 就是一个内联的回调函数。每当 DOM 元素挂载时,React 会调用该回调,并将 DOM 元素作为参数传入。内联函数写法使得代码更加简洁,适合不需要在其他地方使用 ref 的情况。

使用场景

  • 动态引用 DOM 元素 :如果你需要动态访问不同的 DOM 元素(例如多个同类型的元素),回调形式的 ref 非常有用。每当元素挂载或卸载时,回调函数会被自动调用,从而让你能够及时访问或清理引用。
  • 条件渲染 :在某些条件下渲染不同的 DOM 元素,并需要访问它们时,回调形式的 ref 可以确保你在元素实际挂载后才获得对它的引用。

三、createRef(推荐)

createRef 是 React 16.3 引入的一个新 API,是现代 React 中推荐使用的 ref 创建方式。与回调函数形式不同,createRef 提供了一种更加可靠和清晰的方式来引用 DOM 元素或组件实例,并且与每个组件实例绑定,确保 ref 在组件的生命周期内保持一致。

为什么推荐使用 createRef?

createRef 创建的 ref 是专人专用的 ,每个组件实例都会拥有一个独立的 ref 对象。在组件的生命周期内,ref 的 current 属性会保持对相应 DOM 元素的引用,且不会因为重新渲染而发生变化,这使得它比回调形式的 ref 更加稳定和高效。

在类组件中的使用

scala 复制代码
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myDivRef = React.createRef();  // 使用 createRef 创建 ref
  }

  componentDidMount() {
    console.log(this.myDivRef.current);  // 通过 current 获取 DOM 元素
  }

  render() {
    return <div ref={this.myDivRef}>Hello</div>;
  }
}

在这段代码中,我们通过 React.createRef() 创建了一个 ref,并将其赋值给 this.myDivRef。每个组件实例都会拥有一个独立的 myDivRef。当组件挂载时,this.myDivRef.current 会指向 DOM 元素,且在组件的生命周期内不会变化,保证了 ref 的一致性。

在函数组件中的使用

对于函数组件,createRef 并不常用。函数组件通常使用 useRef 来代替 createRef。useRef 会返回一个带有 current 属性的对象,类似于 createRef,但它在函数组件中更为常见,并且会在组件的整个生命周期内保持不变。

javascript 复制代码
import React, { useRef, useEffect } from 'react';

function MyComponent() {
  const myDivRef = useRef(null);

  useEffect(() => {
    console.log(myDivRef.current);  // 通过 current 获取 DOM 元素
  }, []);  // 仅在挂载时调用

  return <div ref={myDivRef}>Hello</div>;
}

在这个例子中,useRef 创建了一个 ref,并将其传递给 div 元素。myDivRef.current 会指向该 DOM 元素。与 createRef 相似,useRef 的 current 属性在组件的整个生命周期内保持不变,适合需要持续引用 DOM 元素的场景。

createRef 和 useRef 的主要区别

  • 类组件中使用 createRef :createRef 在类组件中使用时,每个组件实例都会有一个独立的 ref 对象,它是专人专用的,且在组件生命周期内保持一致,不会因重新渲染而变化。
  • 函数组件中使用 useRef :在函数组件中,useRef 是代替 createRef 的常用方式,提供了与 createRef 类似的功能,且它的引用对象在整个生命周期内保持稳定,避免了回调形式 ref 的频繁创建。

使用场景

  • 类组件中的引用 :对于类组件,createRef 是管理 ref 的推荐方式,它保证了每个组件实例拥有独立的、稳定的引用。
  • 函数组件中的引用 :在函数组件中,useRef 是创建 ref 的标准方式,它提供了与 createRef 类似的功能,适合需要持久引用的场景。

结语✒️

持续更新中......🚀🚀🚀

相关推荐
Java后端的Ai之路6 小时前
06-React-Props
前端·react.js·前端框架
Flynt7 小时前
开源"间谍卫星"说数据全是真的,我把它的免key数据源挨个试了一遍
前端·开源·数据可视化
Csvn7 小时前
渲染管线
前端
程序员大阳7 小时前
副队长CSS教程(33)–圆角与透明
前端·css·透明·圆角
志尊宝7 小时前
Vue3 零基础每日笔记(082):文件上传实战——el-upload 校验、自定义上传、头像预览
前端·javascript·vue.js·笔记·#javascript·#vue.js
鬼手点金8 小时前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
柳杉8 小时前
借助 Codex 和可视化工作流,从调研到完整实现,3D 大屏竟然可以这么简单
前端·ai编程·数据可视化
IMPYLH8 小时前
HTML 的 <wbr> 元素
前端·html
Dovis(誓平步青云)9 小时前
常用命令藏得太深?怎么做一个快捷命令坞
运维·前端·自动化·音视频·prometheus
IT_陈寒10 小时前
Vite的这个问题坑了我三天,原来如此解决!
前端·人工智能·后端