场景
需要根据某个DOM元素的高度,控制另一个DOM元素的显隐。通过回调形式的ref能在首次渲染时获取到该节点的实际高度,但是如果这个节点的高度动态改变,则不能实时监听到该节点的高度
参考链接:https://legacy.reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node
import React, { useState, useCallback } from "react";
import ReactDOM from "react-dom";
function MeasureExample() {
const [list, setList] = useState(["1"]);
const [height, setHeight] = useState(0);
const measuredRef = useCallback((node) => {
if (node !== null) {
setHeight(node.getBoundingClientRect().height);
}
}, []);
return (
<>
{height > 30 ? <div>高度超过30px</div> : null}
<div ref={measuredRef}>
{list.map((r) => (
<div>{r}</div>
))}
</div>
<button
onClick={() => {
setList([...list, 3]);
}}
>
增加
</button>
</>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<MeasureExample />, rootElement);
点击增加时,并不能监听到该节点高度的变化,不会显示“高度超过30px”这句话
解决
通过ResizeObserver监听DOM元素的高度变化
import React, { useState, useRef, useEffect } from "react";
import ReactDOM from "react-dom";
function MeasureExample() {
const [list, setList] = useState(["1"]);
const [show, setShow] = useState(false);
const demoRef = useRef(null);
useEffect(() => {
const resize = new ResizeObserver((e) => {
if (!Array.isArray(e) || !e.length) return;
for (const ent of e) {
const height = ent.contentRect.height;
if (height > 30) {
setShow(true);
} else {
setShow(false);
}
}
});
if (demoRef.current) {
resize.observe(demoRef.current);
}
return () => {
if (demoRef.current) {
resize.unobserve(demoRef.current);
}
};
}, []);
return (
<>
{show ? <div>高度超过30px</div> : null}
<div ref={demoRef}>
{list.map((r) => (
<div>{r}</div>
))}
</div>
<button
onClick={() => {
setList([...list, 3]);
}}
>
增加
</button>
</>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<MeasureExample />, rootElement);
点击增加时会监听到DOM高度的变化,从而显示“高度超过30px”这句话