马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
业务要在屏幕宽度变化时做点事——换布局、换图片、跑埋点。直觉做法是监听 resize,但它在移动端会误伤:用户上下滑一下,导航栏收起,可视高度变了,resize 就白白触发一次。这篇对比两种方案,并给出宽度判断的实现。
方法一:监听 resize 事件
最直接:
window.addEventListener('resize', () => {
console.log(window.innerWidth, window.innerHeight);
});
PC 上拖窗口,宽高数值实时跟着变,够用。问题出在移动端。
移动浏览器把地址栏分成两种状态:页面在顶部时地址栏显示,往下滑后地址栏自动隐藏。地址栏一收,浏览器可视高度就变大了——高度变了,resize 照样触发。用户只是上下翻页,你的宽度相关逻辑却被白跑一次,轻则抖动,重则布局来回跳。
1.1 给 resize 加一道宽度过滤
最朴素的修法:初始化时用一个变量存下当前宽度,回调里比对,只有真变了才执行业务。
let lastWidth = window.innerWidth;
window.addEventListener('resize', () => {
const currentWidth = window.innerWidth;
if (currentWidth === lastWidth) return; // 只有宽度变化才继续
lastWidth = currentWidth;
onWidthChange(currentWidth);
});
代价是得多维护一个 lastWidth 变量。接着看方法二,能把这个变量也省掉。
方法二:用 ResizeObserver 观察根元素
ResizeObserver 监听的是「元素边界尺寸」的变化,而不是整个视口。于是我们可以观察 document.documentElement(html 根元素)的边界,用它当作屏幕宽度的代理。
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
const { width, height } = entry.contentRect;
console.log('宽度:', width, '高度:', height);
}
});
resizeObserver.observe(document.documentElement);
每个被观察元素在回调里都带一个 contentRect 对象,里面有 width、height 等边界信息。关键点在于:
- 当 html 元素本身没有 width / height / padding / margin 这些边界样式时,
contentRect.width 就等于浏览器可视区宽度;
- 移动端上下滑导致地址栏收起时,变的是高度、根元素宽度没动,Observe 就不会触发——正好把误触发挡在外面。
两种方案怎么选
| 维度 | resize 事件 | ResizeObserver |
| 触发精度 | 宽高任一变化都触发 | 只观察目标元素边界 |
| 额外变量 | 需要 lastWidth 记录旧值 | 不需要 |
| 移动端误触发 | 存在(地址栏收放) | 不存在 |
| 兼容性 | 全平台 | 现代浏览器(IE 不支持) |
| 适用场景 | PC 后台、简单布局 | 需要精确监听宽度的移动端页面 |
进阶:用 matchMedia 订阅断点
如果业务逻辑本质是「跨过某个断点就换布局」,用媒体查询订阅比数宽度更贴合语义:
const mq = window.matchMedia('(max-width: 768px)');
const onChange = (e) => {
console.log(e.matches ? '进入移动端布局' : '回到桌面布局');
};
mq.addEventListener('change', onChange); // 旧版 WebKit 只有 addListener,需按能力判断
注意旧版 WebKit 只支持 addListener,做兼容判断即可。
落地建议
- 纯 PC 页面:
resize 加宽度比对就够,代码最少。
- 需要覆盖移动端:优先 ResizeObserver 观察根元素,避免地址栏抖动带来的假变化。
- 逻辑本质是断点切换:用
matchMedia,可读性和可维护性都更好。
- 无论哪种,回调用防抖(
debounce 100–200ms)包一层,避免拖拽窗口时高频触发。
结论
监听窗口宽度变化有三档解法:resize 事件最简单但要自己存旧宽度过滤;ResizeObserver 观察根元素最干净,天然免疫移动端地址栏抖动;matchMedia 最适合断点型布局。同一段逻辑只有 PC 用的话,第一档就够;要上移动端,直接上第二档。
qidao123.com企服评测-应用市场 编辑提示 |