import React, { useRef } from 'react';
// 1. 子组件:使用 forwardRef 包裹
const FancyInput = React.forwardRef((props, ref) => {
// 将父组件传来的 ref 绑定到内部的 input 元素上
return <input ref={ref} {...props} />;
});
// 2. 父组件
function ParentComponent() {
// 创建一个 ref 对象
const inputRef = useRef(null);
const handleClick = () => {
// 通过 ref 直接操作子组件内部的 input 元素
if (inputRef.current) {
inputRef.current.focus(); // 让输入框获得焦点
}
};
return (
<div>
{/* 将 ref 传递给子组件 */}
<FancyInput ref={inputRef} placeholder="点击按钮试试" />
<button onClick={handleClick}>聚焦输入框</button>
</div>
);
}
export default ParentComponent;
如果你不希望直接暴露整个 DOM 节点,而是希望子组件提供一个明确的“操作手册”,可以结合 useImperativeHandleHook 来实现更精确的控制。
import React, { useRef, useImperativeHandle, forwardRef } from 'react';
const FancyInput = forwardRef((props, ref) => {
const inputRef = useRef(null);
// 使用 useImperativeHandle 自定义暴露给父组件的实例值
useImperativeHandle(ref, () => ({
// 只暴露一个 focus 方法
focus: () => {
inputRef.current.focus();
},
// 甚至可以暴露一个自定义方法
sayHello: () => {
alert('Hello from the input!');
}
}));
return <input ref={inputRef} {...props} />;
});
// 父组件用法不变,但现在只能调用 .current.focus() 或 .current.sayHello()