react ref(建议收藏)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

在 React 开发中,开发者常常会遇到需要直接操作 DOM 元素或访问组件实例的场景。此时,React Ref 就像一把“遥控器”,允许我们打破组件的封装性,直接与底层元素或对象进行交互。无论是聚焦输入框、控制动画,还是集成第三方库,Ref 都是不可或缺的工具。本文将从基础概念到实战案例,逐步解析如何正确使用 Ref,并避免常见陷阱。


一、Ref 是什么?为什么需要它?

1.1 Ref 的核心概念

Ref(Reference)是 React 提供的一种特殊属性,用于直接访问 DOM 元素或 React 组件实例。它打破了 React 的单向数据流和虚拟 DOM 的限制,允许开发者绕过状态(State)和属性(Props)的更新机制,实现对元素的直接操作。

比喻
想象你有一台遥控器(Ref),可以随时控制电视(DOM 元素)的开关,而无需等待电视内部复杂的电路(React 的渲染流程)完成状态更新。

1.2 Ref 与 State 的区别

  • State:用于管理组件内部的数据状态,遵循 React 的响应式更新机制。
  • Ref:提供对 DOM 或实例的直接引用,不触发渲染

例子
聚焦输入框时,通过 Ref 直接调用 focus() 方法比用 State 控制 autofocus 属性更直接高效。


二、Ref 的基础用法

2.1 在类组件中使用 Ref

在类组件中,通过 React.createRef() 创建 Ref,并将其赋值给组件的属性:

class InputFocus extends React.Component {  
  constructor(props) {  
    super(props);  
    // 创建 Ref  
    this.inputRef = React.createRef();  
  }  

  componentDidMount() {  
    // 通过 current 属性访问真实 DOM  
    this.inputRef.current.focus();  
  }  

  render() {  
    return <input ref={this.inputRef} />;  
  }  
}  

关键点

  • createRef() 返回一个空对象,通过 .current 属性获取目标元素。
  • Ref 通常在 componentDidMount 或事件中使用,避免在渲染期间操作 DOM。

2.2 在函数组件中使用 useRef

React 16.8 引入的 useRef 钩子,让函数组件也能轻松使用 Ref:

import { useRef, useEffect } from 'react';  

function InputFocus() {  
  const inputRef = useRef(null);  

  useEffect(() => {  
    inputRef.current.focus();  
  }, []); // 空依赖数组确保仅执行一次  

  return <input ref={inputRef} />;  
}  

对比
| 类型 | 方法 | 语法示例 |
|---------------|-----------------------|-----------------------------------|
| 类组件 | React.createRef() | this.inputRef = React.createRef(); |
| 函数组件 | useRef() | const inputRef = useRef(initialValue); |


三、Ref 的典型应用场景

3.1 自动聚焦输入框

通过 Ref 直接调用 focus() 方法,无需引入额外的 State:

function AutoFocusInput() {  
  const inputRef = useRef();  

  useEffect(() => {  
    inputRef.current.focus();  
  }, []);  

  return <input ref={inputRef} />;  
}  

3.2 手动控制动画

在 React 的虚拟 DOM 中,某些动画需要直接操作元素的样式或属性。例如,使用 Ref 实现点击后放大效果:

function ScaleButton() {  
  const buttonRef = useRef();  

  const handleClick = () => {  
    // 直接修改 style 属性  
    buttonRef.current.style.transform = 'scale(1.2)';  
  };  

  return (  
    <button ref={buttonRef} onClick={handleClick}>  
      点击放大  
    </button>  
  );  
}  

3.3 集成第三方库

当使用非 React 的库(如 D3.js 或第三方图表库)时,Ref 可以获取 DOM 元素供其操作:

function ChartContainer() {  
  const chartRef = useRef();  

  useEffect(() => {  
    // 假设 thirdPartyLib 需要 DOM 元素  
    thirdPartyLib.init(chartRef.current);  
  }, []);  

  return <div ref={chartRef} style={{ width: '400px' }} />;  
}  

四、进阶技巧与注意事项

4.1 Ref 的生命周期与 current 属性

  • Ref 的 current 属性在组件挂载时被赋值,在卸载时设为 null
  • 避免在渲染函数中直接依赖 current,因为这可能导致无限循环(如 ref.current.value 与 State 耦合)。

4.2 跨组件传递 Ref

通过 Props 将 Ref 传递给子组件:

// 父组件  
function Parent() {  
  const childRef = useRef();  

  return (  
    <Child ref={childRef} />  
  );  
}  

// 子组件  
function Child(props, ref) {  
  // 使用 forwardRef 包装  
  return <div ref={ref}>我是子组件</div>;  
}  

// 正确写法  
const Child = forwardRef((props, ref) => {  
  return <div ref={ref}>我是子组件</div>;  
});  

4.3 避免滥用 Ref 的陷阱

  • 不要用 Ref 替代 State:例如,输入框的值应通过 State 管理,而非直接读取 ref.current.value
  • 慎用 Ref 调试:过度依赖 Ref 可能掩盖组件设计问题,影响可维护性。

五、Ref 的高级用法

5.1 Ref 回调函数

通过 ref 属性直接传递回调函数,React 会自动将元素赋值给该函数:

function InputFocus() {  
  const handleRef = (node) => {  
    if (node) {  
      node.focus();  
    }  
  };  

  return <input ref={handleRef} />;  
}  

5.2 自定义 Hook 结合 Ref

将 Ref 的逻辑封装为自定义 Hook,提升代码复用性:

// 自定义 Hook  
function useAutoFocus() {  
  const ref = useRef();  
  useEffect(() => {  
    ref.current.focus();  
  }, []);  
  return ref;  
}  

// 使用 Hook  
function AutoFocusInput() {  
  const inputRef = useAutoFocus();  
  return <input ref={inputRef} />;  
}  

六、总结:合理使用 Ref 的核心原则

  1. 明确场景:仅在 State 或 Props 无法满足需求时使用 Ref。
  2. 保持简洁:避免在渲染函数中直接依赖 Ref 的值。
  3. 谨慎传递:通过 Props 或自定义 Hook 管理 Ref 的复杂性。

通过本文的讲解,开发者可以掌握 React Ref 的核心概念、常见用法及进阶技巧。无论是处理表单、动画,还是集成第三方库,Ref 都能成为你高效开发的得力工具。记住,合理使用 Ref 能提升代码的灵活性,但过度滥用则可能引入不必要的复杂性。

希望本文能帮助你在 React 开发中更自信地驾驭 Ref 的强大能力!

最新发布