为什么移动端 div 的 offsetHeight 始终返回相同高度
问题原因
核心问题和“移动端”没有本质关系,是你的useEffect加了空依赖数组,只会在组件首次挂载完成后执行一次,后续元素高度无论因为什么原因变动,都不会重新读取offsetHeight,变量里存的永远是挂载那一刻的高度快照。
移动端问题更明显,只是因为挂载后触发高度变化的场景远多于桌面端,和你提到的几类因素都有关联,常见诱因包括:
- 动态视口变动:移动端浏览器地址栏收起/弹出、横竖屏切换、底部工具栏显隐都会改变实际可视区大小,响应式布局、用了视口单位的容器高度会跟着变,而这些操作基本都发生在组件挂载之后。
- 资源加载滞后:视频、图片这类会撑开容器的资源,挂载时往往还没加载完成,容器高度只是占位高度;等资源加载完撑开容器时,读高度的effect早就执行结束了。移动端网络环境更复杂,这类延迟更常见。
- 布局偏移:自定义WebFont加载完成后替换默认字体,可能导致文本折行数变化,进而改变容器高度;另外旧版移动内核里
100vh的计算值包含隐藏的地址栏,浏览器UI切换时也会出现高度差。 - effect执行时机的影响:
useEffect本身是在浏览器首次绘制完成后异步执行的,如果挂载后播放器会动态初始化、修改样式,这个effect读到的本身就可能不是最终稳定高度。
可靠实现方案
用浏览器原生的ResizeObserver监听元素本身的尺寸变化即可。这个API就是专门为监听元素尺寸设计的,不管高度变化是窗口缩放、资源加载还是内部内容改动导致的,都能精准触发,性能远好于监听window.resize或者轮询。
代码示例
推荐用useLayoutEffect包裹监听逻辑:它会在DOM更新完成、浏览器绘制前同步执行,读取高度的时机更早,能避免高度更新导致的界面闪烁。完整TSX代码如下:
import { useRef, useLayoutEffect } from 'react'; // 保留你原有的ref命名 const playerWrapperReference = useRef<HTMLDivElement>(null); const videoParentNode = useRef<Node | null>(null); const videoOffsetHeight = useRef<number>(0); useLayoutEffect(() => { const targetEl = playerWrapperReference.current; if (!targetEl) return; // 保存父节点 videoParentNode.current = targetEl.parentNode; // 统一的高度更新方法 const syncHeight = () => { videoOffsetHeight.current = targetEl.offsetHeight; // 如果需要用高度驱动视图更新,换成state存储即可: // setPlayerHeight(targetEl.offsetHeight) }; // 先同步一次初始高度 syncHeight(); // 初始化尺寸观察器 const observer = new ResizeObserver(syncHeight); observer.observe(targetEl); // 组件卸载时清理监听,避免内存泄漏 return () => observer.disconnect(); }, []); // 仅挂载时绑定一次监听,空依赖即可
补充说明
- 依赖数组仍然为空是正常逻辑:监听只需要在挂载时绑定一次,后续元素变动会由观察器主动触发回调,不需要反复绑定销毁。
- 不需要额外监听
window.resize、orientationchange事件:只要元素自身高度因为窗口变化发生了改变,ResizeObserver就会触发;如果窗口变了但元素高度没变,也不会执行多余逻辑。如果高度变化来自内部图片/视频加载(窗口尺寸不变),ResizeObserver也能正常捕获,这是window.resize做不到的。 - 目前所有主流移动端浏览器都原生支持ResizeObserver,常规业务不需要额外兼容。如果需要支持非常老旧的设备,引入对应polyfill即可,不要写定时器轮询高度,性能损耗太高。
- 如果业务对视频加载后的尺寸精度要求极高,可以额外在视频的
loadedmetadata事件里手动调用一次syncHeight做双保险,正常情况下ResizeObserver已经能覆盖这个场景。 - 如果高度异常是
100vh兼容问题导致的,可以搭配CSS的dvh动态视口单位修复,监听逻辑不需要改动。
内容的提问来源于stack exchange,提问作者NQQ
相关产品推荐
相关产品推荐

