应使用 window.innerWidth(含滚动条、不触发回流)并加200–250ms防抖,首次加载需手动调用逻辑,避免用 document.body.clientWidth 等不可靠属性。

直接用 window.addEventListener('resize', handler) 就能监听窗口大小变化,但不加防抖、不选对尺寸属性、不处理首次加载,90% 的页面会出问题——比如布局闪动、图表重绘卡顿、移动端横竖屏切换失效。
resize 事件为什么一拖就卡
用户拖拽浏览器边框时,resize 在 Chrome/Firefox 中可能每 1–2ms 触发一次,连续几十次调用带 DOM 操作的回调,CPU 直接拉满。这不是你代码写得慢,是浏览器原生行为。
- 别在回调里直接读
document.body.clientWidth或改样式——它触发回流(reflow),叠加高频调用就是性能炸弹 - 优先用
window.innerWidth/window.innerHeight:它们不触发回流,且包含滚动条区域,更稳定 - 必须加防抖:200–250ms 是实测平衡点,短于 150ms 仍可能漏判,长于 300ms 用户感知延迟明显
window.innerWidth 和 clientWidth 到底该用哪个
看你要响应的是「用户看到的视口」还是「页面内容区」。绝大多数响应式场景要的是前者。
-
window.innerWidth:浏览器可视区域宽度(含垂直滚动条),随窗口缩放实时更新,无回流开销 -
document.documentElement.clientWidth:CSS 视口宽度(不含滚动条),在box-sizing: border-box下与innerWidth差一个滚动条宽度(通常 12–17px) -
document.body.clientWidth:危险!body 可能有 margin/padding/border,值不可靠,尤其在未重置 CSS 的项目里 - 移动端键盘弹出时,
innerWidth会缩小,clientWidth可能不变——这时只有innerWidth能真实反映可用空间
怎么确保页面一打开就按当前尺寸执行逻辑
resize 事件只在“变化后”触发,页面首次加载时不会自动执行。如果你的导航栏、画布、广告位依赖窗口尺寸初始化,漏掉这一步就会白屏或错位。
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
立即学习“前端免费学习笔记(深入)”;
- 不要只写
window.addEventListener('resize', initLayout) - 必须显式调用一次:
initLayout()放在事件绑定之后,或用 IIFE 包裹 - 避免在
DOMContentLoaded里取尺寸:此时 CSS 可能未完全加载,innerWidth值正确,但元素渲染尺寸可能不准 - 如果逻辑依赖某个 DOM 元素(如
#chart),确保元素已存在再调用,否则加个if (el) { ... }守卫
ResizeObserver 能替代 window.resize 吗
不能直接替代,但它是更精准的补充工具。它解决的是「某个元素自身尺寸变没变」,不是「整个窗口」。
-
ResizeObserver对监听单个可伸缩容器(如侧边栏、卡片网格)极有用,且天生节流、不触发回流 - 但它无法监听 viewport 变化本身:比如用户从 1440px 拉到 1920px,
document.documentElement的contentRect可能不变(因为 HTML 元素没重排) - 真要监听视口,还是得用
window.addEventListener('resize', ...);想监听某块区域,才用observer.observe(el) - 兼容性注意:IE 完全不支持,Safari 13.1+ 才稳定,线上项目仍需 fallback 到
resize+ 防抖
最易被忽略的一点:resize 处理函数里别直接操作 document.fullscreenElement 或依赖 matchMedia 查询结果——这些状态在 resize 过程中可能尚未同步,要等微任务队列清空后读取才准。简单做法是包一层 setTimeout(fn, 0) 或用 Promise.resolve().then(fn)。


















