第八章 React Hooks之useImperativeHandle、forwardRef 父子组件通信

一、专栏介绍 

欢迎加入本专栏!本专栏将引领您快速上手React,让我们一起放弃放弃的念头,开始学习之旅吧!我们将从搭建React项目开始,逐步深入讲解最核心的hooks,以及React路由、请求、组件封装以及UI(Ant Design)框架的使用。让我们一起掌握React,开启前端开发的全新篇章。

二、useImperativeHandle 

useImperativeHandle 是 React 中的一个 Hook,它能让你自定义由 ref 暴露出来的句柄。

文档中明确的说明了,默认情况下,组件不会将它们的 DOM 节点暴露给父组件。举例来说,如果你想要 MyInput 的父组件 能访问到 DOM 节点,你必须选择使用 forwardRef:。

所以这里我们需要先了解forwardRef

三、forwardRef 

forwardRef 允许组件使用 ref 将 DOM 节点暴露给父组件。使用 forwardRef() 让组件接收 ref 并将其传递给子组件。

import { forwardRef } from 'react';

const MyInput = forwardRef(function MyInput(props, ref) {
  return ;
});

四、两者集合以后的案例 

4.1、子组件 

子组件的源码接收三个参数:placeholder占位符、onchange事件以及ref属性。其中,ref属性是由父组件传递给子组件的,与子组件内部的inputRef无关。通过使用这个ref属性,我们可以将子组件中的事件暴露给父组件。

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

export type ChildType = {
  focus: () => void;
  getInputValue: () => Promise;
};

const UseImperativeHandleChildDemo: FC<{
  placeholder?: string;
  onchange: (value: string) => void;
  ref: React.Ref;
}> = forwardRef(({ placeholder, onchange }, ref) => {
  // 这里是定义该组件内的input框的ref属性,和上面的ref有点不一样的是,上面的ref是由父组件传进来,获取子组件(本组件)内部的方法。
  const inputRef: React.MutableRefObject = useRef(null);

  useImperativeHandle(
    ref,
    () => {
      const focus = () => {
        return inputRef.current?.focus?.();
      };

      const getInputValue = () => {
        return new Promise((resolve, reject) => {
          if (inputRef.current?.value) {
            resolve(inputRef.current?.value);
          } else {
            reject('您没有输入任何值');
          }
        });
      };

      return { focus, getInputValue };
    },
    []
  );

  return (
     onchange(e.target.value)} />
  );
});
export default UseImperativeHandleChildDemo;

4.2、父组件 

父组件中使用到了一个ChildType类型是由上面的子组件暴露出来的,定义这个类型是让我们更方便的获取到子组件通过ref暴露出来的方法有那些。

import React, { useRef } from 'react';
import UseImperativeHandleChildDemo, { ChildType } from './UseImperativeHandleChildDemo';

function UseImperativeHandleDemo() {
  const inputRef = useRef(null);

  // 通过传递给子组件的ref实现子组件input框聚焦
  const handleClick = () => {
    inputRef.current?.focus();
  };

  const getInputValue = () => {
    inputRef.current
      ?.getInputValue()
      .then((value) => {
        console.log('-----------------点击按钮获取到的值', value);
      })
      .catch((e) => {
        console.log('-----------------', e);
      });
  };

  return (
    
{ console.log('-----------------chang事件', value); }} />
); } export default UseImperativeHandleDemo;

4.3、使用组件 

通过执行这些代码以后,在浏览器控制台你就能观察到相应的信息

import React from 'react';
import UseImperativeHandleDemo from './Demo/UseImperativeHandleDemo';

function App() {
  return (
    
); } export default App;

五、总结 

useImperativeHandle和forwardRef都是React Hooks的一部分,它们的作用和重要性如下:

useImperativeHandle是一个用于暴露自定义ref属性和自定义方法的钩子函数。它使得父组件可以通过ref访问子组件中定义的方法和属性,从而实现对子组件的精细控制。也就是说,父组件可以使用子组件的方法或者控制子组件。当使用useImperativeHandle时,需要子组件中的第二个参数(ref)当作useImperativeHandle的第一个参数。

forwardRef是一个高阶组件,用于将引用(ref)从父组件转发到子组件。这对于访问子组件的DOM元素非常有用。在父组件中,可以通过使用forwardRef来触发子组件的功能。

总的来说,useImperativeHandle和forwardRef都是React中非常重要的钩子和函数,它们可以帮助开发者更好地控制组件的行为和属性,提高代码的可读性和可维护性。

你可能感兴趣的:(前端,javascript,开发语言,React语法,前端框架)