防抖函数在resize场景中用于等待用户停止缩放后执行一次重绘,避免高频触发导致卡顿;通过setTimeout延时执行并清除前序定时器实现,推荐延迟150ms,绑定时使用addEventListener并配合requestAnimationFrame优化重绘性能。

防抖函数在窗口缩放(resize)场景中,核心目标是:**等用户真正停止拖拽/缩放窗口后,再执行一次重绘逻辑**,避免高频触发导致性能问题。关键在于“缩放结束”的判定——浏览器不会主动通知“缩放已完成”,必须靠防抖的时间阈值来模拟这个“结束”。
为什么不能直接监听 resize 并立即重绘?
用户拖拽浏览器边框时,resize 事件可能每秒触发数十次甚至上百次。若每次触发都调用布局计算、DOM 更新或 Canvas 重绘,会严重卡顿,尤其在低端设备或复杂页面上。防抖通过设定等待时间(如 150ms),只保留最后一次触发后的执行,有效过滤中间抖动。
基础防抖实现 + resize 绑定
写一个简单可靠的防抖函数,并绑定到 window.resize:
注意:务必使用 addEventListener,避免重复绑定;首次调用前先清除旧监听器(如有)。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 定义防抖函数,接收处理函数和延迟毫秒数(推荐 100–200ms)
- 用
setTimeout和clearTimeout控制执行时机 - 使用
{ passive: true }提升滚动/缩放事件响应性能(虽对 resize 无实际影响,但属良好实践) - 首次绑定时建议加
immediate: false模式(即非立即执行,而是等停顿后执行)
示例代码:
function debounce(func, wait) {
let timeout;
return function executedFunction() {
const later = () => {
clearTimeout(timeout);
func.apply(this, arguments);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// 你的重绘逻辑(例如更新图表尺寸、调整栅格、重设 canvas 大小等)
function handleResize() {
// ✅ 这里放所有需要「缩放结束后」才执行的重绘操作
console.log('窗口缩放结束,开始重绘');
redrawEverything(); // 自定义函数:重置布局、刷新 Canvas、重排 Grid 等
}
// 绑定防抖后的处理函数
const debouncedResize = debounce(handleResize, 150);
window.addEventListener('resize', debouncedResize);
// ⚠️ 卸载时记得移除监听(例如在 SPA 页面销毁时)
// window.removeEventListener('resize', debouncedResize);
进阶:兼容 Safari/iOS 的 resize 延迟与 Orientation 变化
iOS Safari 在横竖屏切换或某些缩放操作中,resize 触发有延迟或不触发。为更鲁棒,可补充监听 orientationchange(仅 iOS)并共用同一防抖实例:
- 把
debouncedResize同时绑定到resize和orientationchange - 部分 Android 浏览器也可能在全屏/沉浸模式切换时漏掉 resize,可额外监听
visualViewport的resize事件(现代浏览器支持) - 如需精确获取新尺寸,应在
handleResize内实时读取window.innerWidth/window.innerHeight或document.documentElement.clientWidth,不要缓存旧值
重绘优化建议(避免“重绘”本身成为瓶颈)
即使防抖了触发时机,重绘逻辑本身也需高效:
- 用
requestAnimationFrame包裹重绘主逻辑,确保在下一帧执行,避免强制同步布局(Layout Thrashing) - 批量 DOM 修改:先
display: none父容器 → 修改多个子元素 → 再显示,减少回流次数 - Canvas 重绘前,先检查
canvas.width/height是否真发生变化,避免无意义清空与重绘 - 对 SVG 或大量元素,考虑用
transform: scale()替代重计算尺寸(如响应式缩放)
示例整合 requestAnimationFrame:
function handleResize() {
requestAnimationFrame(() => {
redrawEverything();
});
}
不复杂但容易忽略:防抖不是万能的,它解决的是“频次”,不是“开销”。确保重绘函数本身轻量,才能真正让窗口缩放体验顺滑。

















