React Hook ---- useImperativeHandle

useRef
  • useRef 返回一个可变的 ref 对象,其 current 属性被初始化为传入的参数
  • 返回的对象在组件的整个生命周期内保持不变。
forwardRef
  • 被 React.forwardRef 包裹的组件接受 props 和 ref 作为参数
  • 可以将 ref 从父组件转到子组件的DOM上,使得父组件中可以获取子组件的DOM。
useRef 与 forwardRef 示例
// 父组件
import { useRef } from "react";
import Child from "./Child";

export default function App() {
  const inputRef = useRef();
  const getFocus = () => {
    inputRef.current.focus();
  };

  return (
    <div className="App">
      <Child ref={inputRef} />
      <button onClick={getFocus}>聚焦</button>
    </div>
  );
}

// 子组件
import { forwardRef } from "react";
const Child = forwardRef((props, ref) => {
  return (
    <div>
      <span>子组件</span>
      <input ref={ref} />
    </div>
  );
});
export default Child;

useRef 与 forwardRef 结合使用,将子组件完全保留给父组件,父组件可以进行任意操作,这样的可控性并不好。一般父组件需要啥,子组件就暴露啥,这样更好。useImperativeHandle 就可以做到。

useImperativeHandle
useImperativeHandle(ref, createHandle, [deps])
  • 第一个参数为父组件传递的 ref
  • 第二个参数是一个函数,返回的一个对象会自动绑定到ref上。 即子组件可以将自己内部的方法或者值通过useImperativeHandle添加到父组件中useRef定义的对象中。
  • 第三个参数是函数依赖的值(可选)。若 createHandle 函数中使用到了子组件内部定义的变量,则还需要将该变量作为依赖变量成为useImperativeHandle第3个参数
  • 需 useRef 和 forwardRef 共同使用

下面这个例子是上面例子的改造:

// 父组件
import { useRef } from "react";
import Child from "./Child";

export default function App() {
  const inputRef = useRef();
  const getFocus = () => {
    inputRef.current.focus();
    console.log(inputRef.current.name);
  };

  return (
    <div className="App">
      <Child ref={inputRef} />
      <button onClick={getFocus}>点击</button>
    </div>
  );
}
// 子组件
import { forwardRef, useImperativeHandle, useRef } from "react";
const Child = forwardRef((props, ref) => {
  const inputRef = useRef(null);
  useImperativeHandle(ref, () => ({
    name: "我是子组件",
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return (
    <div>
      <span>子组件</span>
      <input ref={inputRef} />
    </div>
  );
});
export default Child;


你可能感兴趣的:(React)