React

React-Hooks之useImperativeHandler

2023-02-16  本文已影响0人  YiYa_咿呀
1.什么是useImperativeHandle Hook?

useImperativeHandle可以让你在使用ref 时自定义暴露给父组件的实例值,我的理解就是不让外界随便对通过ref拿到的元素进行操作,maybe我们可以称之为“权限配置"
这里出现了ref,小单简单地回顾一下前几天学习的useRef,可以知道ref就是帮助我们获取某个元素而设定的。
But!!!!!我记得当时说过useRef并不能帮助我们拿到函数式组件,只能帮我们拿到函数式组件中的某个元素,让小单来验证一下吧。

//1. 构造一个函数式组件
import React, {useRef} from 'react';
function Home(props) {
    return (
        <div>
            <p>Home</p>
            <input type="text" placeholder={'请输入内容'}/>
        </div>
    )
// App.js
function App() {
  // 2.创建一个ref
    const appRef = useRef();
    function btnClick() {
//打印一下ref拿到的元素
         console.log(appRef);
         console.log(appRef.current);
    }
    return (
        <div>
            <Home ref={appRef}/>
            <button onClick={()=>{btnClick()}}>获取</button>
        </div>
    )
}

结果如下:可以发现useRef拿不到函数式组件Home,但是控制台给了我们提示,可以使用React.forward()

函数式组件无法通过useref直接获取.png
让我们跟着控制台的提示来尝试一下吧~
我对代码进行了改进
React.forward()和mome一样是一个高阶组件
主要改进
const ForwardHome = forwardRef(Home);

代码如下:

import React, {useRef, forwardRef} from 'react';
//1. 构造一个函数式组件
function Home(props) {
    return (
        <div>
            <input type="text" placeholder={'请输入内容'}/>
        </div>
    )
// App.js
function App() {
  // 2.创建一个ref
    const appRef = useRef();
    function btnClick() {
//打印一下ref拿到的元素
         console.log(appRef);
         console.log(appRef.current);
    }
    return (
        <div>
//用forwardRef返回的ForwardHome代替Home
            <ForwardHome ref={appRef}/>
            <button onClick={()=>{btnClick()}}>获取</button>
        </div>
    )
}

结果如下,这表明我们此时我们通过React.forward()可以拿到函数式组件了

可以获取函数式组件.png
既然可以拿到函数式组件了,那意味着我们也可以对其进行操作,试一下吧~
将btnClick方法添加对其操作的代码:此时页面会自动聚焦并显示设置的文本:
    function btnClick() {
        //打印一下ref拿到的元素
         console.log(appRef);
         console.log(appRef.current);
      //对拿到的元素进行操作
        appRef.current.focus();
        appRef.current.value = '华科上岸,小单冲冲冲!';
    }

但是问题又来了,如果说我并不想让外界通过以上方法随意的对拿到的函数式组件进行操作,只可以进行部分操作(类似于权限控制的说法)该怎么做呢?
此时useImperativeHandler就诞生了!
用法:

1. 导入useImperativeHandle
import React, {useRef, forwardRef, useImperativeHandle} from 'react';
2.创建
//接受的第一个参数是一个ref,第二个参数是一个回调函数,返回其允许进行的操作
useImperativeHandle(appRef, ()=>{
        return {
            myFocus: ()=>{
                inputRef.current.focus();
            }
        }
    });

具体代码:

import React, {useRef, forwardRef, useImperativeHandle} from 'react';
function Home(props, appRef) {
    const inputRef = useRef();
    useImperativeHandle(appRef, ()=>{
        return {
            myFocus: ()=>{
                inputRef.current.focus();
            }
        }
    });
    return (
        <div>
            <p>Home</p>
            <input ref={inputRef} type="text" placeholder={'请输入内容'}/>
        </div>
    )
}
const ForwardHome = forwardRef(Home);
function App() {
    const appRef = useRef();
    function btnClick() {
        // console.log(appRef);
        // console.log(appRef.current);
        appRef.current.focus();
        appRef.current.value = '华科上岸,小单冲冲冲!';
    }
    return (
        <div>
            <ForwardHome ref={appRef}/>
            <button onClick={()=>{btnClick()}}>获取</button>
        </div>
    )
}
export default App;

此时仍然通过 appRef.current.focus();进行操作就不可以,因为useImperativeHandle第二个参数返回的东西里没有这个操作


实现了ref的权限控制.png
终极方案

调用useImperativeHandle定义的myFocus可以实现自动聚焦


import React, {useRef, forwardRef, useImperativeHandle} from 'react';
function Home(props, appRef) {
    const inputRef = useRef();
    useImperativeHandle(appRef, ()=>{
        return {
            myFocus: ()=>{
                inputRef.current.focus();
            }
        }
    });
    return (
        <div>
            <p>Home</p>
            <input ref={inputRef} type="text" placeholder={'请输入内容'}/>
        </div>
    )
}
const ForwardHome = forwardRef(Home);
function App() {
    const appRef = useRef();
    function btnClick() {
        // console.log(appRef);
        // console.log(appRef.current);
        // appRef.current.focus();
       // appRef.current.value = '华科上岸,小单冲冲冲!';
        appRef.current.myFocus();
    }
    return (
        <div>
            <ForwardHome ref={appRef}/>
            <button onClick={()=>{btnClick()}}>获取</button>
        </div>
    )
}
export default App;
上一篇 下一篇

猜你喜欢

热点阅读