防抖函数是 window.resize 场景下防止页面崩溃的必要手段。窗口拖拽时 resize 可一秒触发上百次,直接执行 dom 操作易导致报错、重排卡顿及框架中未挂载组件访问异常;需用 200–300ms 防抖延迟,确保只执行最终尺寸逻辑,并做好元素存在性检查与监听清理。

防抖函数在 window.resize 场景下不是“锦上添花”,而是防止页面崩溃的必要手段。窗口拖拽时,resize 可能在 1 秒内触发上百次,若直接执行 DOM 操作、状态更新或尺寸计算,极易引发控制台报错(如 “Cannot read property of null”)、强制重排卡顿,甚至 Vue/React 中的 unmounted 组件访问异常。
为什么 resize 必须加防抖
浏览器对窗口尺寸变化极其敏感——哪怕轻微拖动边缘,就会连续派发 resize 事件。常见风险包括:
- 反复读取
offsetWidth/clientHeight触发同步布局,拖慢渲染主线程 - 操作已被移除的 DOM 元素(比如组件已销毁,但 resize 回调还在执行)
- 在框架中频繁触发响应式更新,冲垮依赖收集或导致 state 冲突
- 重复初始化 canvas、重绘图表、调整栅格列数,造成资源浪费和视觉闪烁
行内 script 轻量实现防抖
无需引入 Lodash 或构建工具,直接在 HTML 底部写一段干净的防抖逻辑即可生效:
<script></script>
function debounce(fn, delay) {
let timer = null;
return function() {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, arguments), delay);
};
}
const handleResize = () => {
const container = document.getElementById('app');
if (!container) return; // 存在性检查是防错第一道防线
container.dataset.width = window.innerWidth;
console.log('布局已就绪:', window.innerWidth, 'x', window.innerHeight);
};
window.addEventListener('resize', debounce(handleResize, 250));
关键点:
• 延迟设为 200–300ms —— 太短起不到过滤作用,太长用户感知滞后
• debounce 返回新函数,每次触发都重置定时器,确保只执行最后一次
• handleResize 内必须做元素存在判断,避免访问 null 或已卸载节点
Vue 中防抖多个处理逻辑
在 Vue 组件里常需同时更新 canvas、刷新 tooltip 位置、重算响应式栅格。可统一用一个防抖函数包裹多个操作:
- 在
mounted中绑定:window.addEventListener('resize', this.debounce(this.onResize, 300)) -
onResize方法内按需调用:this.updateCanvas()、this.repositionTooltips()、this.calcColumns() - 务必在
beforeUnmount(Vue 3)或beforeDestroy(Vue 2)中移除监听,防止内存泄漏
防抖 vs 节流:resize 场景选哪个
resize 的本质是“等用户停手再响应”,所以防抖比节流更合适:
- 防抖:用户拖完松手后,只执行一次最终尺寸下的逻辑 —— 符合真实交互意图
- 节流:哪怕用户还在拖,也会每隔固定时间执行一次 —— 容易造成中间态布局错乱、canvas 渲染撕裂
- 例外情况极少,比如要做实时缩放预览(极少见),才考虑节流 + requestAnimationFrame 优化
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











