函数式组件父子ref通讯
如果你需要在父组件中同时获取子组件的属性值和子组件内的 DOM 元素(例如 <input>
元素),可以通过在子组件中定义两个 ref
来实现:一个用于暴露子组件的实例方法,另一个用于直接操作 DOM 元素。
修改子组件
在子组件中,你可以定义两个 ref
:一个用于暴露实例方法,另一个用于操作 DOM 元素。然后通过 useImperativeHandle
将 DOM 元素的引用也暴露给父组件。
子组件
tsx
复制
import React, { useRef, useImperativeHandle } from 'react';const ChildComponent = React.forwardRef((props, ref) => {const [value, setValue] = React.useState("Hello, World!");const inputRef = useRef<HTMLInputElement>(null); // 用于操作 DOM 元素的 refuseImperativeHandle(ref, () => ({getValue: () => value,setValue: (newValue) => setValue(newValue),getInputElement: () => inputRef.current, // 暴露 DOM 元素的引用}));return (<div><inputtype="text"value={value}onChange={(e) => setValue(e.target.value)}ref={inputRef} // 将 ref 附加到 input 元素上/></div>);
});export default ChildComponent;
父组件
在父组件中,你可以通过 ref
调用子组件的 getInputElement
方法来获取 <input>
元素的引用。
父组件
tsx
复制
import React, { useRef, useEffect } from 'react';
import ChildComponent from './ChildComponent';const ParentComponent = () => {const childRef = useRef(null);useEffect(() => {// 确保子组件已经渲染完成if (childRef.current) {// 通过 ref 调用子组件的方法const inputValue = childRef.current.getValue();console.log('Input Value:', inputValue);// 获取子组件的 input 元素const inputElement = childRef.current.getInputElement();if (inputElement) {console.log('Input Element:', inputElement);inputElement.focus(); // 例如,聚焦到输入框}}}, []);const changeChildValue = () => {if (childRef.current) {childRef.current.setValue("New Value from Parent");}};return (<div><ChildComponent ref={childRef} /><button onClick={changeChildValue}>Change Child Value</button></div>);
};export default ParentComponent;