目录
1.需求
由于在项目开发过程中,我们往往时需要调用子组件中的方法。例如管理系统中的添加,就需要我们调用添加表单时展示的方法。从而实现页面的展示。在vue中我们知道可以给组件上添加ref从而获取到组件的实例对象。那么在React中我们该怎么办呢、
2.页面
2.1父组件
下面就是我们的父组件,其实就是类似于一个网站的头部,当我们点击用户登录时,就需要将我们写登录逻辑的页面展示出来。因此我们就需要调用对应的Ref从而帮助我们操作对应的子组件的方法。
const WebHeader = () => { const ModelRef = useRef<IFnChildInstance>(null) const ChildrenFn = ModelRef.current! function userLogin(){ ChildrenFn.showModal() console.log(ChildrenFn.showModal) } return ( <div className="header-container fx fa"> <div className="wrapper fx jb fa"> <div className="left-wrapper fx fa"> <img src="http://syt.atguigu.cn/_nuxt/img/logo.7086376.png" alt="网站loge" style={{width:'50px'}}/> <span className='text link'>尚医通 预约挂号统一平台</span> </div> <div className="right-wrapper fx jb"> <span className='link-to'>帮助中心</span> <span className='link-to' onClick={userLogin}>登录注册</span> <Child ref={ModelRef}></Child> </div> </div> </div> ) }
2.2 子组件
这里的子组件就超级简单了,我们就只是在这里定义了一个弹窗从而实现登录的逻辑。这里就只是简单的将子组件中的弹出的方法暴露给父组件,从而让父组件点击登录的时候可以展开我们对应的子组件。
const Child = forwardRef<IFnChildInstance>((props,ref) => { const [isModalOpen, setIsModalOpen] = useState(false); useImperativeHandle(ref, () => ({ showModal, //(实际等于: resetSharePopup:resetSharePopup) })); function showModal(){ setIsModalOpen(true); }; return( <Modal title="Basic Modal" open={isModalOpen}> <p>Some contents...</p> <p>Some contents...</p> <p>Some contents...</p> </Modal> ) })
3.实现逻辑
3.1 父组件中构建ref
由于我们需要获取到对应的子组件的ref,因此我们首先需要在父组件中获取到对应的。由于我们这里定义的是函数式组件,因此在这里我们就使用了对应的hooks,如useRef。因为这里我们使用了TS,因此我们对创建的Ref进行了类型的限制。
const ModelRef = useRef<IFnChildInstance>(null)
因为在这里我们主要是获取子组件中打开弹窗的方法,因此我们采取的是只是暴露方法,而不需要将DOM元素暴露出来。因此其中的IFnChildInstance就是我们定义的接口类型。其中的showModal的类型是一个无返回值的函数。然后我们将定义好的ref放在对应的组件,到这里我们的父组件中所实现的相关操作已经完成了。
interface IFnChildInstance { showModal: () => void, } //组件引用的地方 <Child ref={ModelRef}></Child>
3.2子组件中的相关操作
首先我们需要使用的是forwardRef来进行向外暴露。下面是官方文档中对其的介绍。
forwardRef
允许你的组件使用 ref 将一个 DOM 节点暴露给父组件。
forwardRef(render)
使用 forwardRef()
来让你的组件接收一个 ref 并将其传递给一个子组件:
import { forwardRef } from 'react'; const MyInput = forwardRef(function MyInput(props, ref) { // ... });
props
:父组件传递过来的参数。ref
:父组件传递的ref
属性。ref
可以是一个对象或函数。如果父组件没有传递一个 ref,那么它将会是null
。你应该将接收到的ref
转发给另一个组件,或者将其传递给 useImperativeHandle。- 对应的官方文档的链接如下,需要的可以跳转过去仔细查看forwardRef – React
回归正题,我们这里就使用forwardRef来进行对应的创建。代码如下。由于我们在父组件中传递的ref所对应的类型是IFnChildInstance,因此我们在这里接收的时候也要进行变量类型的生命。然后由于我们子组件只需要将其对应的方法暴露给父组件中操作,而不是将整个DOM元素给父组件,因此我们可以使用useImperativeHandle来进行操作。其中对应的具体使用方法可以点击上面的连接进行查看。这里就只是简单阐述了,第一个参数接收的是函数传递的ref,第二个使我们想向外暴露的方法。该参数的类型是一个函数,因此这里我们就使用了赋值的心事。第三个参数是一个数组,具体的使用方法还请查看官方文档。然后我们还需要在子组件中定义所传递给父组件中的方法。注意的是其函数的类型要和我们所定义的ref的类型一样,否则TS会给我们报错提示。
const Child = forwardRef<IFnChildInstance>((props,ref) => { const [isModalOpen, setIsModalOpen] = useState(false); useImperativeHandle(ref, () => ({ showModal, //(实际等于: resetSharePopup:resetSharePopup) })); function showModal(){ setIsModalOpen(true); }; return( <Modal title="Basic Modal" open={isModalOpen}> <p>Some contents...</p> <p>Some contents...</p> <p>Some contents...</p> </Modal> ) })
4.父组件使用
然后我们就可以通过父组件中定义的接口useRef的变量中的.current属性来获取我们子组件中传递返回的对象,其中就是我们所定义返回的函数。然后我们就只需要在合适的地方将其调用即可。
const ModelRef = useRef<IFnChildInstance>(null) const ChildrenFn = ModelRef.current! function userLogin(){ ChildrenFn.showModal() console.log(ChildrenFn.showModal)
5.总结
首先我们需要使用useRef来创建对应的ref的值,但是我们需要给对应的值定义接口。其中接口的信息就是我们想往外暴露的值
然后再对应的组件上使用ref来进行获取对应的标签
然后在子组件中我们需要使用forwardRef向外暴露一个可操作的ref。其中的值为props和ref,分别与之对父组件传递值时的接口
useImperativeHandle(ref,()=>{({})},[])的形式只是暴露我们所需要的方法或者参数,其他的就不用暴露给父组件,这样方便于我们操作
然后就完成了操作子组件的相关方法。
该总结只是作为我刚使用TS完成父子组件调用值。可能会有啥总结的不正确或者文章中有啥错误也可以指出讨论。共同进步