美文网首页
如何实现拿到子组件是函数组件的ref?

如何实现拿到子组件是函数组件的ref?

作者: 不详7 | 来源:发表于2023-03-20 11:11 被阅读0次

    一、前言

    众所周知,函数组件是没有实例的,所以是没有自己的ref的,如果使用useRef()来定义,始终是null,所以如何拿到子组件是函数组件的ref呢?我们使用的是forwardRef 和useImperativeHandle结合的方式。

    二、介绍forwardRef 

    React.forwardRef 会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中。这种技术并不常见,但在以下两种场景中特别有用:

    1、转发 refs 到 DOM 组件

    2、在高阶组件中转发 refs

    总结:forwardRef 就是允许将子组件中某个组件的ref,透传给他的父组件。

    用法示例:

    import React, { forwardRef, useImperativeHandle, useRef } from 'react';

    //A---父组件

    const A = ()=>{

        const bRef = useRef(null)

        return (<B  ref={bRef} />)

    }

    //B---子组件,C---子子组件

    const  B =   forwardRef ((props,ref)=>{

        let b='这是个变量'

        const b1=()=>{};

        const b2=()=>{};

        return <C  ref={ref} />

    })

    上述中bRef 拿到的就是C的ref,但是有个前提C组件必须是个类组件 不能是函数组件,或者C是个input这一类的基础标签。

    注意:这个时候bRef ,只有C实例上面的方法和dom,是没有b变量和b1、b2方法的。那如果想让bRef有B组件的b变量和b1方法,就需要用到useImperativeHandle。

    三、介绍useImperativeHandle

    useImperativeHandle可以让你在使用ref时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用ref这样的命令式代码。useImperativeHandle应当与forwardRef一起使用。

    用法:useImperativeHandle(ref, createHandle, [deps])。

    通过useImperativeHandle可以只暴露特定的操作,将父组件传入的ref和useImperativeHandle第二个参数返回的对象绑定到了一起。

    作用: 减少暴露给父组件获取的DOM元素属性, 只暴露给父组件需要用到的DOM方法。

    示例:解决上面bRef中没有b变量和b1方法问题。

    A组件不变:

    const A = ()=>{    const bRef = useRef(null)    return (<B  ref={bRef} />)}

    把上面例子中B组件改写为:

    const  B =   forwardRef ((props,ref)=>{

         let b='这是个变量'

         const b1=()=>{};

          const b2=()=>{};

         useImperativeHandle(ref, () => ({    b: b,    b1: b1  }));//仅仅多了一行代码,需要什么传什么

         return <C  ref={ref} />

    })

    此时在父组件A中的bRef中,不仅有C的ref全部内容,也有了子组件B的 b变量和b1方法 ,间接实现了 父组件拿到子组件是函数组件的ref。

    相关文章

      网友评论

          本文标题:如何实现拿到子组件是函数组件的ref?

          本文链接:https://www.haomeiwen.com/subject/htpurdtx.html