React开发中createRef和自定义Ref对象该怎么选

来源:个人站长网作者:美谷头衔:网络博主
导读:本期聚焦于小伙伴创作的《React开发中createRef和自定义Ref对象该怎么选》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《React开发中createRef和自定义Ref对象该怎么选》有用,将其分享出去将是对创作者最好的鼓励。

在React组件开发中,ref是获取DOM元素、类组件实例的重要方式,官方提供了createRef方法来创建ref对象,同时开发者也可以根据自身需求封装自定义Ref对象。两种方式都能实现引用管理,但适用场景和底层逻辑存在明显差异,需要根据实际需求做出选择。

React开发中createRef和自定义Ref对象该怎么选

createRef的基本用法与原理

createRef是React官方提供的用于创建ref对象的方法,调用后会返回一个可变的ref对象,其current属性会被初始化为null,当ref被挂载到组件或DOM元素上时,current属性会被赋值为对应的实例或DOM节点。

以下是createRef的基础使用示例:

import React, { createRef, Component } from 'react';

class DemoComponent extends Component {
  constructor(props) {
    super(props);
    // 创建ref对象
    this.inputRef = createRef();
  }

  handleFocus = () => {
    // 通过current属性获取DOM节点并调用方法
    this.inputRef.current.focus();
  };

  render() {
    return (
      <div>
        <input ref={this.inputRef} type="text" />
        <button onClick={this.handleFocus}>聚焦输入框</button>
      </div>
    );
  }
}

export default DemoComponent;

createRef的底层实现非常简单,核心逻辑就是返回一个包含current属性的对象:

function createRef() {
  const refObject = {
    current: null
  };
  return refObject;
}

需要注意的是,createRef每次调用都会返回一个新的ref对象,因此在类组件中通常会将createRef的调用放在构造函数中,避免每次渲染都创建新的ref导致不必要的更新。

自定义Ref对象的实现方式

自定义Ref对象本质上是开发者自行封装的、符合ref使用规范的对象,核心要求也是包含current属性,因为React在挂载ref时,只会检查对象是否存在current属性并进行赋值。常见的自定义Ref场景包括需要监听ref变化、扩展ref能力等情况。

以下是一个自定义Ref对象的示例,实现了ref赋值时的监听功能:

import React, { Component } from 'react';

class CustomRefDemo extends Component {
  constructor(props) {
    super(props);
    // 自定义ref对象,添加赋值监听逻辑
    this.customRef = {
      current: null,
      // 重写current的赋值逻辑
      set _current(value) {
        console.log('ref被赋值,值为:', value);
        this.current = value;
      }
    };
  }

  componentDidMount() {
    // 手动触发ref赋值(实际场景中由React自动赋值)
    this.customRef._current = document.getElementById('customInput');
  }

  render() {
    return (
      <div>
        <input id="customInput" type="text" />
      </div>
    );
  }
}

export default CustomRefDemo;

更常见的自定义Ref场景是结合回调函数使用,回调函数形式的ref本身也可以看作一种自定义Ref的实现,React会在组件挂载或卸载时调用回调函数,传入对应的DOM节点或实例:

import React, { Component } from 'react';

class CallbackRefDemo extends Component {
  handleInputRef = (node) => {
    // node为对应的DOM节点,挂载时为节点,卸载时为null
    if (node) {
      console.log('输入框已挂载');
      node.focus();
    } else {
      console.log('输入框已卸载');
    }
    this.inputNode = node;
  };

  render() {
    return (
      <div>
        <input ref={this.handleInputRef} type="text" />
      </div>
    );
  }
}

export default CallbackRefDemo;

两者的核心差异对比

createRef和自定义Ref对象的核心差异主要体现在以下几个方面:

对比维度createRef自定义Ref对象
创建方式调用React官方提供的createRef方法开发者自行封装对象,只要包含current属性即可
可扩展性仅包含current属性,无法直接扩展额外逻辑可以自定义current的读写逻辑,添加额外方法或监听
适用场景常规DOM获取、类组件实例获取场景需要监听ref变化、扩展ref能力、特殊引用管理场景
函数组件兼容性函数组件中可以使用,但每次渲染会创建新对象,通常配合useRef使用函数组件中也可以自定义,但需要自行管理对象稳定性

场景选择建议

优先选择createRef的场景

  • 仅需要获取DOM元素或类组件实例,不需要额外的监听或扩展逻辑
  • 在类组件中使用ref,不需要在函数组件重新渲染时保持ref对象的稳定性
  • 项目遵循React官方推荐的最佳实践,不需要自定义ref相关逻辑

优先选择自定义Ref对象的场景

  • 需要在ref被赋值或清空时执行额外的逻辑,比如打日志、触发回调
  • 需要给ref对象添加额外的属性或方法,扩展ref的能力
  • 使用回调函数形式的ref,需要更灵活的引用管理逻辑
  • 需要兼容旧版本的React,或者有特殊的上层框架集成需求

注意事项

无论是使用createRef还是自定义Ref对象,都需要注意以下几点:

  • ref不能用于函数组件,因为函数组件没有实例,若需要获取函数组件的引用,需要将其转为类组件或者使用forwardRef
  • 不要在渲染过程中读取或写入ref的current属性,可能会导致不可预期的问题
  • 自定义Ref对象时,必须保证存在current属性,否则React无法正确完成ref的挂载赋值
  • 在函数组件中如果需要使用类似createRef的能力,官方推荐使用useRef,useRef返回的对象会在组件的整个生命周期内保持不变,避免每次渲染创建新对象的问题

以下是函数组件中使用useRef的示例,它本质和createRef类似,但更适合函数组件场景:

import React, { useRef, useEffect } from 'react';

function FunctionRefDemo() {
  // useRef创建ref,对象在组件生命周期内保持稳定
  const inputRef = useRef(null);

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

  return (
    <div>
      <input ref={inputRef} type="text" />
    </div>
  );
}

export default FunctionRefDemo;

ReactcreateRef自定义Ref对象ref使用场景修改时间:2026-07-12 17:57:20

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。