使用 React Hooks 以编程方式定位元素
让我们来看看如何使用 React Hooks 来告诉组件应该在页面上的哪个位置渲染。
想象一下你最喜欢的搜索引擎——当我们输入搜索词时,我们可能会在搜索输入框下方看到一个自动完成框:让我们创建这个浮动元素。
TLDR;
在这个 codesandbox 中可以找到问题和解决方案的完整示例。
那么,让我们开始吧。现在先不赘述细节,在这个例子中,你会看到我们常用的解决方案:如果有内容要显示,我们就显示该元素。你还会发现,这种方案会导致显示时所有后续元素向下移动。这不太理想。
使其充满活力
首先,我们来为容器添加一些样式,使其悬浮在其他元素之上:
.searchresultsfloat {
position: absolute;
z-index: 1;
}
使用引用
现在,在我们的故事中,我们需要知道我们要将位置信息链接到哪个元素,这时 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">
当新引用的元素渲染时,它会将自身的信息填充到 `.current` 变量中。然后,我们可以调用该引用的 `getBoundingClientRect()` 函数来获取元素的位置信息。
让我们在 useEffect hook 中执行此操作,以便我们知道在获取引用元素的位置时页面已渲染。
React.useEffect(() => {
if (searchBarReference.current) {
setSearchResultTop(searchBarReference.current.getBoundingClientRect().bottom);
}
}, []);
完美!但还不完全是:现在元素已经渲染到正确的位置了。但是当我们调整屏幕大小时,你会发现结果元素的位置错了:
使用布局效果
这时 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);
}, []);
这里我们创建一个监听器,等待调整大小事件。当事件发生时,我们会重新确认引用元素的边界,以便更新结果,使其显示在我们想要的位置。这样,当我们调整屏幕大小时,就能在正确的位置看到结果。
务必返回一个用于移除监听器的函数,这样当页面卸载时,监听器就不会继续等待更多事件。瞧!
就是这样。
所以我们使用 useRef 来确定元素的位置,并使用 useLayoutEffect 在 DOM 发生变化时进行更新。皆大欢喜!
和往常一样:这并非唯一的解决方案,只是我找到的一种。如果您想联系我,请随时联系!
文章来源:https://dev.to/joepurnell1/programmatically-positioning-elements-with-react-hooks-aef

