likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 19

前言

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

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

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

这时问题就来了:

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

JS如何使用?

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

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

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>
  )
}

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

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

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

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

TS如何使用?

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

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

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

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

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>
  )
}
const  Child = forwardRef((props, ref:ForwardedRef<HTMLDivElement>) => {
  return (
    <div ref={ref} style={{height: '50vh', width: '100%'}}>
        这是子容器
    </div>
  )
})

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

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

为什么?

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

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

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

转载自:https://juejin.cn/post/7262252440439308347
评论
请登录