发布于 2026-01-06 4 阅读
0

使用 React Hooks 以编程方式定位元素

使用 React Hooks 以编程方式定位元素

让我们来看看如何使用 React Hooks 来告诉组件应该在页面上的哪个位置渲染。

想象一下你最喜欢的搜索引擎——当我们输入搜索词时,我们可能会在搜索输入框下方看到一个自动完成框:让我们创建这个浮动元素。

TLDR;

在这个 codesandbox 中可以找到问题和解决方案的完整示例

那么,让我们开始吧。现在先不赘述细节,在这个例子中,你会看到我们常用的解决方案:如果有内容要显示,我们就显示该元素。你还会发现,这种方案会导致显示时所有后续元素向下移动。这不太理想。

使其充满活力

首先,我们来为容器添加一些样式,使其悬浮在其他元素之上:

.searchresultsfloat {
  position: absolute;
  z-index: 1;
}
Enter fullscreen mode Exit fullscreen mode

使用引用

现在,在我们的故事中,我们需要知道我们要将位置信息链接到哪个元素,这时 useRef 就派上用场了。我们可以使用 useRef 创建一个引用,然后将其绑定到 DOM 元素。

// Create our reference
const searchBarReference = React.useRef(null);

// Other React Pizzazz...

// Attach it to the element we want to judge our position against
<div ref={searchBarReference} className="box blue searchcontainer">
Enter fullscreen mode Exit fullscreen mode

当新引用的元素渲染时,它会将自身的信息填充到 `.current` 变量中。然后,我们可以调用该引用的 `getBoundingClientRect()` 函数来获取元素的位置信息。

让我们在 useEffect hook 中执行此操作,以便我们知道在获取引用元素的位置时页面已渲染。

React.useEffect(() => {
  if (searchBarReference.current) {
    setSearchResultTop(searchBarReference.current.getBoundingClientRect().bottom);
  }
}, []);
Enter fullscreen mode Exit fullscreen mode

完美!但还不完全是:现在元素已经渲染到正确的位置了。但是当我们调整屏幕大小时,你会发现结果元素的位置错了:

解决方案:容器在调整大小时移动

使用布局效果

这时 useLayoutEffect hook 就派上用场了。这个 hook 看起来和我们标准的 useEffect hook 一样,唯一的区别是它会在所有 DOM 变更之后触发。我们可以利用这一点:

React.useLayoutEffect(() => {
  function updatePosition() {
    setSearchResultTop(searchBarReference.current.getBoundingClientRect().bottom);
  }
  window.addEventListener('resize', updatePosition);
  updatePosition();
  return () => window.removeEventListener('resize', updatePosition);
}, []);
Enter fullscreen mode Exit fullscreen mode

这里我们创建一个监听器,等待调整大小事件。当事件发生时,我们会重新确认引用元素的边界,以便更新结果,使其显示在我们想要的位置。这样,当我们调整屏幕大小时,就能在正确的位置看到结果。

务必返回一个用于移除监听器的函数,这样当页面卸载时,监听器就不会继续等待更多事件。瞧!

可根据尺寸调整而自动调整的解决方案

就是这样。

所以我们使用 useRef 来确定元素的位置,并使用 useLayoutEffect 在 DOM 发生变化时进行更新。皆大欢喜!

和往常一样:这并非唯一的解决方案,只是我找到的一种。如果您想联系我,请随时联系!

文章来源:https://dev.to/joepurnell1/programmatically-positioning-elements-with-react-hooks-aef