在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项目中,我们每写一个东西都要考虑类型的问题,这样我们才可以避免出错。

相关推荐
Bigger3 小时前
Tauri (26)——托盘图标总对不上系统主题?一行 Template Image 搞定
前端·rust·app
kyriewen5 小时前
面试官问你:“AI 能写 80% 的代码了,公司为什么还需要你?”
前端·javascript·面试
甲维斯6 小时前
又升级咯!坦克大战2026,科技与复古并存!
前端·人工智能·游戏开发
搬砖的码农8 小时前
(08)为什么我的 Agent 一跑后台服务就卡死
前端·agent·ai编程
飘尘8 小时前
前端转全栈(Java 后端)必须要知道的:开发中的锁机制与分布式并发控制
前端·后端·全栈
亲亲小宝宝鸭8 小时前
前端性能监控:web-vitals
前端·性能优化·监控
陆枫Larry9 小时前
可滚动页面背景填不满:`height: 100vh` vs `min-height: 100vh`
前端
Patrick_Wilson9 小时前
Squash Merge 的血缘陷阱:为什么删掉的代码又活了过来
前端·git·程序员
kyriewen10 小时前
今天的科技圈,全在抢英伟达的饭碗
前端·面试·ai编程