# React技巧之使用ref获取元素宽度

原文链接:https://bobbyhadz.com/blog/react-get-element-width-ref (opens new window)

作者:Borislav Hadzhiev (opens new window)

正文从这开始~

# 总览

在React中,使用ref获取元素的宽度:

  1. 在元素上设置ref属性。
  2. useLayoutEffect钩子中,更新宽度的state变量。
  3. 使用offsetWidth属性获取元素宽度。
import {useLayoutEffect, useRef, useState} from 'react';

export default function App() {
  const ref = useRef(null);

  const [width, setWidth] = useState(0);
  const [height, setHeight] = useState(0);

  useLayoutEffect(() => {
    setWidth(ref.current.offsetWidth);
    setHeight(ref.current.offsetHeight);
  }, []);
 
  return (
    <div ref={ref}>
      <h2>Width: {width}</h2>

      <h2>Height: {height}</h2>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

useRef()钩子可以传递一个初始化作为参数。该钩子返回一个可变ref对象,其.current属性被初始化为传递的参数。

请注意,我们必须访问ref对象的current属性,以获得对我们设置ref属性的div元素的访问。

当我们为元素传递ref属性时,比如说,<div ref={myRef} /> 。React将ref对象的.current属性设置为相应的DOM节点。

# useLayoutEffect

我们传递一个空的依赖数组到useLayoutEffect 钩子上,所以它只会在组件挂载时运行。

useLayoutEffect(() => {
  setWidth(ref.current.offsetWidth);
  setHeight(ref.current.offsetHeight);
}, []);
1
2
3
4

useLayoutEffect钩子与useEffect相同,但在所有DOM突变后同步触发。useLayoutEffect 钩子经常被用来从DOM中读取布局。

我们使用了useLayoutEffect钩子,因为我们需要等待元素上的ref被设置,并且在访问其offsetHeightoffsetWidth属性之前,元素被渲染。

offsetWidth属性以像素为单位返回元素的宽度,包括任何边框、内填充和垂直滚动条(如果存在的话)。

offsetHeight属性返回元素的高度,单位是像素,包括垂直内填充和边框。

或者,你可以使用clientWidth属性,它返回元素的宽度,单位是像素,包括内填充,但不包括边框、外边距和垂直滚动条(如果存在的话)。

useLayoutEffect(() => {
  setWidth(ref.current.clientWidth);
  setHeight(ref.current.clientHeight);
}, []);
1
2
3
4

# 总结

我们通过ref来获取元素的宽度和高度,主要是在useLayoutEffect钩子中通过ref.current来引用DOM元素,获取元素上面的offsetWidthoffsetHeight