在TS中,React如何使用ref获取子组件的Dom结构?

前言

最近在业务开发时,突然遇到一个关于TS的业务问题。这个具体业务是:首先有个一个父容器,父容器内有三个子容器,点击分页按钮,让父容器滚动到对应子容器模块。 这个我们就涉及到了一个问题:由于要考虑到不同屏幕的适配问题,父容器滚动的距离需要根据子容器的高度来确定,所以我们需要获取到子容器的高度。

当时第一时间我没有将子容器分成组件来实现,所以我们直接使用Ref就很容易的拿到了子容器的高度。实现了该功能。但由于父容器的代码量越来越大,我就将子容器分成子组件开发。这是当我再去使用Ref实现时,TS就开始报如下的错误了。

这时问题就来了:

  • 在JS中我们可以如何获取到子组件的Dom结构呢?
  • 在TS中我们又该在JS的基础上添加那些东西才可以获取到子组件的Dom结构呢?
  • 为什么需要添加这些东西呢?

JS如何使用?

首先我们来解决第一个问题:在JS中,父子组件是怎么使用ref的?

我先准备好父组件,关键代码如下:

javascript 复制代码
function App() {
  const [height, setHeight] = useState(0)
  const childRef = useRef(null)
  const getHeight = () => {
    console.log(childRef.current.clientHeight);
    setHeight(childRef.current.clientHeight)
  }
  return (
    <div>
      <Child ref={childRef}></Child>
      <button onClick={getHeight}>获取子容器的高度:{height}</button>
    </div>
  )
}

父组件准备完了,我们再看看子组件代码:

javascript 复制代码
const  Child = forwardRef((props, ref) => { // 这个ref就是
  return (
    <div ref={ref} style={{height: '50vh', width: '100%'}}>
        这是子容器
    </div>
  )
})

接下来我们就来看看上述两份代码是怎么实现, 首先我们需要用forwardRef, 它是React中用于在函数组件中获取对另一个组件的引用的API, 它帮我们绝解决的问题是组件引用时用,并循环嵌套或组件嵌套过深的问题。 它允许我们在组件函数中获取对另一个组件的引用, 并将这个引用作为参数传递给组件。 这样我们再在子组件上绑定一个ref属性,通过forwardRef传给了父组件,这样父组件就可以拿到子组件的Dom结构。

TS如何使用?

上面我们看完了JS的实现,那接下来我们就该看看TS版啦。如果我们直接把JS代码搬到TS上,我们来看看会有什么效果?

它报了上述两个ts的类型错误。那我们就需要给他们加上类型,代码如下:

javascript 复制代码
function App() {
  const [height, setHeight] = useState<number>(0)
  const childRef = useRef<HTMLDivElement>(null)
  const getHeight = () => {
    console.log(childRef.current!.clientHeight);
    setHeight(childRef.current!.clientHeight)
  }
  return (
    <div>
      <Child ref={childRef}></Child>
      <button onClick={getHeight}>获取子容器的高度:{height}</button>
    </div>
  )
}
javascript 复制代码
const  Child = forwardRef((props, ref:ForwardedRef<HTMLDivElement>) => {
  return (
    <div ref={ref} style={{height: '50vh', width: '100%'}}>
        这是子容器
    </div>
  )
})

如上述代码所示,我们给他加上了两个类型,分别是ForwardedRef<HTMLDivElement><HTMLDivElement>,我们就解决了第一个类型错误, 我们再给childRef.current加上一个断言,我们就解决了第二个错误。我们也就实现了如下的效果。

为什么?

我们来看看这两个东西是什么:

  • HTMLDivElement: 在 TypeScript 中,HTMLDivElement 是一个类型声明(type declaration),用于表示 HTML DOM 中的 <div> 元素。通过使用 HTMLDivElement 类型,你可以在 TypeScript 代码中明确指定某个变量、函数参数、返回值等的类型为 <div> 元素。
  • ForwardedRef: 在 TypeScript 中,ForwardedRef 是一个泛型类型,用于定义一个转发引用。它通常用于在组件中将 ref 属性传递给子组件,以便对子组件的引用进行操作。我们通过使用 ForwardedRef 将 ref 进行转发,确保正确地传递ref。

相比于JS,TS给了我们更多的类型限制,在上述代码中,不难看出我们根本没有修改逻辑问题,只是通过TS来限定了类型。所以在TS项目中,我们每写一个东西都要考虑类型的问题,这样我们才可以避免出错。

相关推荐
橙序员小站2 小时前
Agent Skill 是什么?一文讲透 Agent Skill 的设计与实现
前端·后端
炫饭第一名4 小时前
速通Canvas指北🦮——基础入门篇
前端·javascript·程序员
王晓枫5 小时前
flutter接入三方库运行报错:Error running pod install
前端·flutter
符方昊5 小时前
React 19 对比 React 16 新特性解析
前端·react.js
ssshooter5 小时前
又被 Safari 差异坑了:textContent 拿到的值居然没换行?
前端
曲折5 小时前
Cesium-气象要素PNG色斑图叠加
前端·cesium
Forever7_5 小时前
Electron 淘汰!新的桌面端框架 更强大、更轻量化
前端·vue.js
不会敲代码15 小时前
前端组件化样式隔离实战:React CSS Modules、styled-components 与 Vue scoped 对比
css·vue.js·react.js
Angelial5 小时前
Vue3 嵌套路由 KeepAlive:动态缓存与反向配置方案
前端·vue.js
jiayu6 小时前
Angular学习笔记24:Angular 响应式表单 FormArray 与 FormGroup 相互嵌套
前端