在React的数据流世界里,ref是一个有点特别的逃生口。它让你能直接访问DOM元素或者React组件实例,跳过props和state的那套更新机制。简单说,ref就是你通向真实DOM或组件实例的一根“直达线”。
![图片[1]-什么是React的Ref?怎么用?-速码派](http://www.sumapai.com/wp-content/uploads/2026/01/5a3494fa093642c3bd47d2ec4b89bdbd_tplv-tb4s082cfz-aigc_resize_1080_1080-1024x683.webp)
为什么要用ref?直接操作DOM的时候
大部分时候,你应该让React通过状态来管理DOM。但有些情况你非得自己来:
- 管理焦点、文本选中,或者媒体播放。
- 触发命令式动画。
- 集成需要直接操作DOM的第三方库(比如一个老旧的jQuery插件)。
在这些场景下,你就需要ref来拿到那个真实的DOM节点。
用useRef创建和管理
在函数组件里,我们用useRef这个Hook来创建ref。
import { useRef } from 'react';
function MyComponent() {
const myInputRef = useRef(null);
const handleClick = () => {
myInputRef.current.focus(); // 直接调用DOM API
};
return (
<>
<input ref={myInputRef} type="text" />
<button onClick={handleClick}>聚焦输入框</button>
</>
);
}
useRef返回一个可变的ref对象,它的.current属性被初始化为你传入的参数(null)。当你把myInputRef传给JSX的ref属性时,React会自动把DOM节点赋值给myInputRef.current。
不仅仅是DOM:存任何可变值
ref的另一个妙用是当作一个“盒子”,用来存放那些你希望在组件生命周期内持久存在,但又不想触发重新渲染的值。
function Timer() {
const intervalRef = useRef();
useEffect(() => {
intervalRef.current = setInterval(() => {
// 做些事情
}, 1000);
return () => clearInterval(intervalRef.current);
}, []);
}
这里我们把定时器ID存在intervalRef.current里。即使组件重新渲染,这个值也会保持不变,而且改变它不会导致组件重新渲染。这非常适合存储前一个状态、计时器ID或者其他实例变量。
回调ref:更精细的控制
偶尔你需要更灵活地控制ref的赋值。这时可以用“回调ref”,传一个函数给ref属性。
<input ref={(node) => { if (node) node.focus(); }} />
这个函数会在组件挂载时接收到DOM元素(node),在卸载时接收到null。你可以在函数里做任何事。
用ref要小心。它破坏了React声明式的模型,算是命令式的编程。所以,能靠state和props解决的问题,就别用ref。把它留给那些真正需要直接接触DOM或实例的“脏活”。




























暂无评论内容