• react中ref、createRef、useRef、forwardRef以及useImperativeHandle


    一、ref

      ref是React提供的用来操纵React组件实例或者DOM元素的接口。表示为对组件真正实例的引用,其实就是ReactDOM.render()返回的组件实例。

      ref可以挂到任何元素上,可以挂到组件上也可以挂载到DOM元素上。

      Class组件中使用ref:

      在React的Class组件时期,我们通过createRef创建ref

    class MyComponent extends React.Component {
      constructor(props) {
        super(props);
        this.inputRef = React.createRef();
      }
    
      render() {
        return <input type="text" ref={this.inputRef} />;
      }
    
      componentDidMount() {
        this.inputRef.current.focus();
      }
    }

      在这个例子里ref挂到了原生DOM元素<input />,在这种情况下可以通过ref.current获取到这个DOM元素,并直接调用上面的方法。

      ref如果挂在到一个Class组件上,这样ref.current获取到的就是这个Class组件的实例。

      函数式组件中使用ref:

        但是,ref不能挂到一个函数式组件(除非使用forwardRef,因为:ref回调函数会在组件被挂载之后将组件实例传递给函数,函数式组件没有实例。

      在函数式组件中通过useRef创建ref 

    function TextInputWithFocusButton() {
      const inputEl = useRef(null);
      const onButtonClick = () => {
        inputEl.current.focus();
      };
      return (
        <>
          <input ref={inputEl} type="text" />
          <button onClick={onButtonClick}>Focus the input</button>
        </>
      );
    }

    二、createRef和useRef的区别

           createRef 只能用在class组件中,useRef 只能用在函数式组件中。

      createRef 每次渲染都会返回一个新的引用,而 useRef 每次都会返回相同的引用。

      如果在函数式组件中使用createRef创建的ref,其值会随着函数式组件的重新执行而不断初始化。hooks不能用在class组件中,所以class组件只能使用createRef。

    三、forwardRef

      前面我们说到:ref不能挂到一个函数式组件(除非使用forwardRef)。

      forwardRef可以直接包裹一个函数式组件,被包裹的函数式组件会获得被分配给自己的ref(作为第二个参数)。

      如果你直接将ref分配给没有被forwardRef包裹的函数式组件,React会在控制台给出错误。

    const App: React.FC = () => {
      const ref = useRef(null);
    
      useEffect(() => {
        ref.current.focus();
      }, []);
    
      return (
        <>
          <Child ref={ref} />
        </>
      );
    };
    
    const Child = forwardRef((props, ref: Ref<any>) => {
      return <input type="text" name="child" ref={ref} />;
    });

       **注意:React.forwardRef参数必须是function,而这个API通常用来解决HOC(高阶组件)中丢失ref的问题。

    四、useImperativeHandle

       在forwardRef例子中的代码实际上是不推荐的,因为无法控制要暴露给父组件的值,所以我们使用useImperativeHandle控制要将哪些东西暴露给父组件。

       useImperativeHandle 应当与 forwardRef 一起使用:

       调用方式: 

    useImperativeHandle(ref, createHandle, [deps])
    • 接收一个ref
    • 接收一个函数,这个函数返回的对象即是要暴露出的ref
    • 类似useEffect,接收一个依赖数组
    const FancyInput=(props, ref) =>{
      const inputRef = useRef();
      useImperativeHandle(ref, () => ({
        focus: () => {
          inputRef.current.focus();
        }
      }));
      return <input ref={inputRef} />;
    }
    export default forwardRef(FancyInput);

      在本例中,渲染 <FancyInput ref={inputRef} /> 的父组件可以调用 inputRef.current.focus()

  • 相关阅读:
    通用标签
    网页基础
    WCF---服务发布的步骤
    锁·——lock关键字详解
    C# 实现磁性窗体
    C#中的线程(三) 使用多线程
    C#中的线程(二) 线程同步基础
    C#中的线程(一)入门
    class A<T> where T:class 这个泛型类中的Where T:class什么意思
    OO真经——关于面向对象的哲学体系及科学体系的探讨(下)
  • 原文地址:https://www.cnblogs.com/gg-qq/p/15078913.html
Copyright © 2020-2023  润新知