我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

在前面的forwardRef的相关文章中,苏南大叔曾经说过,可以通过ref访问到类式组件里面的变量以及方法。而同时,并不能使用ref访问到函数式组件里面的变量及方法。

苏南大叔:react教程,通过useImperativeHandle暴露函数组件内部函数 - useImperativeHandle
react教程,通过useImperativeHandle暴露函数组件内部函数(图4-1)

苏南大叔的程序如此灵动博客,记录苏南大叔和计算机代码的故事。本文描述,react项目通过ref访问组件内部函数或变量的方法。特别说明的是,使用useImperativeHandle访问函数式组件的方法。测试环境:create-react-app@5.0.1react@18.2.0react-dom@18.2.0node@16.14.2

前置阅读项目

下面的两篇文章,可能会对您正确理解本文用例有帮助:

苏南大叔:react教程,通过useImperativeHandle暴露函数组件内部函数 - 运行截图说明
react教程,通过useImperativeHandle暴露函数组件内部函数(图4-2)

访问类式组件方法和变量(基础对比例子)

访问类式组件内部的方法或者变量,就是顺理成章的事情,只需要对子组件的实例设置了正确的ref即可。

【注意:就是ref字样】
import React, { useRef, Component, useEffect } from 'react';
class Sunan1 extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    }
  }
  var1 = "sunan大叔";
  setCount(cnt) {
    this.setState((state) => { return { "count": cnt } })
  }
  increase() {
    this.setState((state) => { return { "count": state.count + 1 } })
  }
  render() {
    return (
      <div>
        <p>【类式子组件,父组件可直接通过ref访问】次数:{this.state.count}</p>
      </div>
    )
  }
}
const App = () => {
  const ref = useRef(null);
  useEffect(()=>{
    console.log(ref.current.var1);
  },[])
  return <div>
    <button onClick={() => ref.current.increase()}>父节点控制函数组件计数加1</button>
    <button onClick={() => ref.current.setCount(100)}>重置计数值100</button>
    <Sunan1 ref={ref} />
  </div>
}
export default App;

苏南大叔:react教程,通过useImperativeHandle暴露函数组件内部函数 - 类式组件访问数据
react教程,通过useImperativeHandle暴露函数组件内部函数(图4-3)

访问函数式组件方法和变量(使用场景)

先提出问题:
但是同样的需求,在函数式组件这边却变得异常复杂。首先,函数式组件的实例,不能直接设置ref属性,会有警告信息。除非:
1、使用forwardRef,但是转过的ref就很可能变了指代对象了。
2、不设置ref,换个名字比如ref2,使用props.ref2来获得引用。不过,也有转移指代对象的嫌疑。

再使用useImperativeHandle解决这个问题,范例代码如下:

import React, { useState, useImperativeHandle, useRef, Component, useEffect } from 'react';
const Sunan2 = ({ ref2 }) => {
  const [count, setCount] = useState(0)
  const var1 = "苏南大叔";
  useImperativeHandle(ref2, () => ({
    increase, setCount, var1
  }))
  const increase = () => {
    setCount((v) => v + 1)
  }
  return <div>
    <p>【函数子组件,需要useImperativeHandle】次数:{count}</p>
  </div>
}
const App = () => {
  const ref2 = useRef(null);
  useEffect(()=>{
    console.log(ref2.current.var1);
  },[])
  return <div>
    <button onClick={() => ref2.current.increase()}>父节点控制函数组件计数加1</button>
    <button onClick={() => ref2.current.setCount(100)}>重置计数值100</button>
    <Sunan2 ref2={ref2} />
  </div>
}
export default App

苏南大叔:react教程,通过useImperativeHandle暴露函数组件内部函数 - 函数组件访问数据
react教程,通过useImperativeHandle暴露函数组件内部函数(图4-4)

核心代码:

useImperativeHandle(ref2, () => ({
    increase, setCount, var1
}))

把要暴露出去的函数或者变量,都放在上面即可,用逗号分割。用起来是不是就和module.exports={}很类似?

另外,在函数式组件里面,通过props传递的ref2引用,最终也没有绑定到某个具体的对象或者元素上。仅仅是和useImperativeHandle产生了联系。

结束语

更多react经验文章,点击下面的链接:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   react