在vue组合式api中可以通过父组件定义ref ,子组件属性上定义同名ref,父组件就可以获取子组件实例,在子组件上通过调用defineExpose 暴露属性或者方法
那在react 如何做呢,
forwardRef
forwardRef 允许你的组件使用 将一个 DOM 节点暴露给父组件
简单来说:使用 forwardRef,你可以在函数式组件中传递 ref,将它们转发给内部的子组件。从而获取子组件信息
默认情况下,每个组件的 DOM 节点都是私有的。然而,有时候将 DOM 节点公开给父组件是很有用的,比如允许对它进行聚焦。如果你想将其公开,可以将组件定义包装在 forwardRef() 中:
import { forwardRef } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
const { label, ...otherProps } = props;
return (
<label>
{label}
<input {...otherProps} />
</label>
);
});
你将在 props 之后收到一个 ref 作为第二个参数。将其传递到要公开的 DOM 节点中:
import { forwardRef } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
const { label, ...otherProps } = props;
return (
<label>
{label}
<input {...otherProps} ref={ref}/>
</label>
);
});
这样,父级的 Form 组件就能够访问 MyInput 暴露的 <input> DOM 节点:
function Form() {
const ref = useRef(null);
function handleClick() {
ref.current.focus();
}
return (
<form>
<MyInput label="Enter your name:" ref={ref} />
<button type="button" onClick={handleClick}>
Edit
</button>
</form>
);
}
那如果想在父组件中使用子组件的属性或者方法应该怎么做呢?
useImperativeHandle
useImperativeHandle 是 React 中的一个 Hook,它能让你自定义由 ref 暴露出来的句柄。
useImperativeHandle(ref, createHandle, dependencies?)
参数
ref:该ref是你从forwardRef渲染函数 中获得的第二个参数。createHandle:该函数无需参数,它返回你想要暴露的 ref 的句柄。该句柄可以包含任何类型。通常,你会返回一个包含你想暴露的方法的对象。- 可选的
dependencies:函数createHandle代码中所用到的所有反应式的值的列表。反应式的值包含 props、状态和其他所有直接在你组件体内声明的变量和函数。倘若你的代码检查器已 为 React 配置好,它会验证每一个反应式的值是否被正确指定为依赖项。该列表的长度必须是一个常数项,并且必须按照[dep1, dep2, dep3]的形式罗列各依赖项。React 会使用Object.is来比较每一个依赖项与其对应的之前值。如果一次重新渲染导致某些依赖项发生了改变,或你没有提供这个参数列表,你的函数createHandle将会被重新执行,而新生成的句柄则会被分配给 ref。
父组件: 定义一个ref 传递给子组件MyInput
mport { useRef } from 'react';
import MyInput from './MyInput.js';
export default function Form() {
const ref = useRef(null);
function handleClick() {
ref.current.focus();
// 下方代码不起作用,因为 DOM 节点并未被暴露出来:
// ref.current.style.opacity = 0.5;
}
return (
<form>
<MyInput label="Enter your name:" ref={ref} />
<button type="button" onClick={handleClick}>
Edit
</button>
</form>
);
}
子组件:通过 forwardRef 获得ref,通过 useImperativeHandle 暴露子组件的属性或者方法
import { forwardRef, useRef, useImperativeHandle } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
const inputRef = useRef(null);
useImperativeHandle(ref, () => {
return {
focus() {
inputRef.current.focus();
},
scrollIntoView() {
inputRef.current.scrollIntoView();
},
};
}, []);
return <input {...props} ref={inputRef} />;
});
export default MyInput;