← JavaScript onload事件 没有下一篇了 →

JavaScript onresize事件

原创 2026-03-23 JavaScript 已有人查阅

JavaScript onresize 事件:响应窗口尺寸变化

在网页开发中,用户调整浏览器窗口大小是一个很常见的操作。有些页面需要在窗口尺寸变化时做出响应,比如重新布局、调整元素尺寸、或者隐藏某些内容。onresize 事件就是用来处理这种场景的。

我最早用到 resize 事件是在做一个响应式图表组件的时候。图表库初始化时根据容器宽度绘制,窗口改变后如果不重新绘制,图表就会变形或者显示不全。加了 resize 监听之后,问题就解决了。

什么是 onresize 事件?

onresize 事件在浏览器窗口大小被调整时触发。它可以绑定在 window 对象上(最常用),也可以绑定在某些可调整大小的元素上。

触发时机:用户拖拽窗口边缘、较大化/小化窗口、或者用 JavaScript 修改窗口尺寸时,都会触发 resize 事件。

获取窗口尺寸的方法

在 resize 事件中,经常需要获取当前窗口或元素的尺寸。JavaScript 提供了多个属性来获取尺寸信息:

属性 作用 说明
window.innerWidth / innerHeight 浏览器视口尺寸 包含滚动条占用的空间
window.outerWidth / outerHeight 浏览器窗口整体尺寸 包含工具栏、边框等
element.clientWidth / clientHeight 元素内部尺寸 包含内边距,不包含边框和滚动条
element.offsetWidth / offsetHeight 元素布局尺寸 包含边框和内边距
element.scrollWidth / scrollHeight 元素滚动内容尺寸 包含溢出部分

onresize 的三种绑定方式

和其他事件一样,resize 也有三种绑定方式。下面通过具体的代码示例来理解,示例采用“代码号”学习环境的写法。

方式一:HTML 属性方式

在 <body> 标签上使用 onresize 属性。

<!DOCTYPE html>
<html>
<head>
    <script>
        let resizeCount = 0;
        
        function handleResize() {
            resizeCount++;
            let width = window.innerWidth;
            let height = window.innerHeight;
            
            document.getElementById("sizeInfo").innerHTML = 
                "当前视口尺寸: " + width + " x " + height;
            document.getElementById("countInfo").innerHTML = 
                "窗口被调整了 " + resizeCount + " 次";
        }
    </script>
</head>
<body onresize="handleResize()">
    <h3>onresize 事件示例(HTML 属性方式)</h3>
    <p>尝试调整浏览器窗口的大小,下面的信息会实时更新</p>
    
    <div id="sizeInfo" style="padding: 10px; background-color: #f8f9fa; margin: 10px 0;">
        当前视口尺寸: 等待调整...
    </div>
    <div id="countInfo" style="padding: 10px; background-color: #e8f4fd;">
        窗口被调整了 0 次
    </div>
</body>
</html>

说明:每次调整窗口,handleResize 函数就会被调用,显示当前视口尺寸和调整次数。这种写法适合简单场景,但 HTML 和 JavaScript 耦合在一起。

方式二:DOM 属性方式

在 JavaScript 里给 window.onresize 赋值。

<!DOCTYPE html>
<html>
<body>
    <h3>onresize 事件示例(DOM 属性方式)</h3>
    <p>调整窗口大小,观察下方数值变化</p>
    
    <div id="displayArea" style="padding: 15px; border: 1px solid #ccc; margin-top: 20px;">
        宽度: -- | 高度: --
    </div>
    <div id="outerInfo" style="margin-top: 10px; color: #666;">
        外层窗口尺寸: --
    </div>

    <script>
        let displayDiv = document.getElementById("displayArea");
        let outerInfo = document.getElementById("outerInfo");
        
        // 绑定 resize 事件
        window.onresize = function() {
            let innerW = window.innerWidth;
            let innerH = window.innerHeight;
            let outerW = window.outerWidth;
            let outerH = window.outerHeight;
            
            displayDiv.innerHTML = `视口宽度: ${innerW}px | 视口高度: ${innerH}px`;
            outerInfo.innerHTML = `浏览器窗口尺寸: ${outerW} x ${outerH}`;
            
            // 根据窗口宽度改变背景色(演示效果)
            if (innerW < 600) {
                displayDiv.style.backgroundColor = "#ffe6e6";
            } else if (innerW < 1000) {
                displayDiv.style.backgroundColor = "#e6ffe6";
            } else {
                displayDiv.style.backgroundColor = "#e6e6ff";
            }
        };
        
        // 初始化一次,显示初始尺寸
        window.onresize();
    </script>
</body>
</html>

说明:窗口调整时,实时显示视口尺寸和浏览器窗口尺寸,并根据宽度改变背景色。注意这里用 window.onresize() 主动调用一次,让页面加载时就有数据显示。

注意:DOM 属性方式如果后面再次赋值,会覆盖之前的函数。如果需要多个监听,用 addEventListener 更合适。

方式三:addEventListener 方式

这是推荐的做法,可以绑定多个处理函数。

<!DOCTYPE html>
<html>
<head>
    <style>
        .card {
            padding: 15px;
            margin: 10px 0;
            border-radius: 5px;
            transition: all 0.2s;
        }
        .card-1 { background-color: #d4edda; border-left: 4px solid #28a745; }
        .card-2 { background-color: #fff3cd; border-left: 4px solid #ffc107; }
        .card-3 { background-color: #cce5ff; border-left: 4px solid #007bff; }
    </style>
</head>
<body>
    <h3>addEventListener 方式绑定 resize 事件</h3>
    <p>调整窗口大小,下面三个模块会独立响应</p>
    
    <div id="module1" class="card card-1">模块1: 等待窗口调整...</div>
    <div id="module2" class="card card-2">模块2: 等待窗口调整...</div>
    <div id="module3" class="card card-3">模块3: 等待窗口调整...</div>

    <script>
        let mod1 = document.getElementById("module1");
        let mod2 = document.getElementById("module2");
        let mod3 = document.getElementById("module3");
        
        // 第一个处理函数:显示视口尺寸
        function updateSizeInfo() {
            let w = window.innerWidth;
            let h = window.innerHeight;
            mod1.innerHTML = `模块1 - 当前视口: ${w} x ${h}`;
        }
        
        // 第二个处理函数:根据宽度调整文字大小
        function adjustFontSize() {
            let w = window.innerWidth;
            let fontSize = Math.max(12, Math.min(24, w / 50));
            mod2.innerHTML = `模块2 - 根据宽度动态调整文字大小: ${fontSize.toFixed(1)}px`;
            mod2.style.fontSize = fontSize + "px";
        }
        
        // 第三个处理函数:显示调整次数
        let resizeCounter = 0;
        function countResize() {
            resizeCounter++;
            mod3.innerHTML = `模块3 - 窗口已调整 ${resizeCounter} 次,时间: 2026年3月23日`;
        }
        
        // 绑定多个处理函数
        window.addEventListener("resize", updateSizeInfo);
        window.addEventListener("resize", adjustFontSize);
        window.addEventListener("resize", countResize);
        
        // 初始化调用一次,让数据显示出来
        updateSizeInfo();
        adjustFontSize();
        countResize();
    </script>
</body>
</html>

说明:三个模块各自响应 resize 事件,分别做不同的事情:显示尺寸、调整字体、记录次数。用 addEventListener 可以轻松管理多个独立逻辑,互不干扰。

实战示例:响应式布局适配

在项目中,resize 事件常用于实现响应式布局。比如根据窗口宽度决定侧边栏的显示方式。

<!DOCTYPE html>
<html>
<head>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        .container {
            display: flex;
            min-height: 100vh;
            transition: all 0.3s;
        }
        .sidebar {
            width: 250px;
            background-color: #2c3e50;
            color: white;
            padding: 20px;
            transition: width 0.3s;
        }
        .sidebar.collapsed {
            width: 60px;
        }
        .sidebar.collapsed .sidebar-text {
            display: none;
        }
        .content {
            flex: 1;
            padding: 20px;
            background-color: #ecf0f1;
        }
        .toggle-btn {
            background-color: #3498db;
            color: white;
            border: none;
            padding: 8px 15px;
            cursor: pointer;
            border-radius: 4px;
        }
        .status-bar {
            margin-top: 20px;
            padding: 10px;
            background-color: white;
            border-radius: 4px;
            font-size: 14px;
        }
        @media (max-width: 768px) {
            .sidebar {
                width: 180px;
            }
            .sidebar.collapsed {
                width: 50px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="sidebar" id="sidebar">
            <h3 class="sidebar-text">导航菜单</h3>
            <ul style="margin-top: 20px; list-style: none;">
                <li class="sidebar-text"> 项目列表</li>
                <li class="sidebar-text" style="margin-top: 10px;"> 设置</li>
                <li class="sidebar-text" style="margin-top: 10px;"> 统计</li>
            </ul>
        </div>
        <div class="content">
            <button class="toggle-btn" id="toggleBtn">收起侧边栏</button>
            <div class="status-bar" id="resizeStatus">
                窗口宽度: 等待调整...
            </div>
            <p style="margin-top: 20px;">调整窗口大小,侧边栏会根据宽度自动适应。</p>
            <p>当窗口宽度小于 768px 时,侧边栏默认宽度会减小。</p>
            <p>当前时间: 2026年3月23日</p>
        </div>
    </div>

    <script>
        let sidebar = document.getElementById("sidebar");
        let toggleBtn = document.getElementById("toggleBtn");
        let statusDiv = document.getElementById("resizeStatus");
        let isCollapsed = false;
        
        // 手动收起/展开侧边栏
        toggleBtn.addEventListener("click", function() {
            isCollapsed = !isCollapsed;
            if (isCollapsed) {
                sidebar.classList.add("collapsed");
                toggleBtn.innerHTML = "展开侧边栏";
            } else {
                sidebar.classList.remove("collapsed");
                toggleBtn.innerHTML = "收起侧边栏";
            }
        });
        
        // 监听窗口尺寸变化,更新状态信息
        function updateWindowInfo() {
            let width = window.innerWidth;
            let height = window.innerHeight;
            statusDiv.innerHTML = `窗口尺寸: ${width} x ${height} | 
                                   视口宽度: ${width}px | 
                                   检测时间: 2026年3月23日`;
            
            // 根据宽度自动调整侧边栏状态(可选)
            if (width < 600 && !sidebar.classList.contains("collapsed")) {
                // 小窗口时自动收起(这里不自动执行,避免干扰用户操作)
                // 实际项目中可以根据需求决定是否自动调整
            }
        }
        
        // 绑定 resize 事件
        window.addEventListener("resize", updateWindowInfo);
        
        // 页面加载时执行一次
        updateWindowInfo();
    </script>
</body>
</html>

说明:这个示例中,resize 事件用于实时显示窗口尺寸。侧边栏的收起/展开由按钮控制,但可以根据需求扩展为根据窗口宽度自动调整布局。

性能优化:防抖(debounce)

resize 事件有一个特点:用户拖拽窗口时,会连续触发很多次。如果每次触发都执行复杂的计算或 DOM 操作,可能会影响性能。这时候就需要用到防抖(debounce)技术。

<!DOCTYPE html>
<html>
<body>
    <h3>resize 事件防抖示例</h3>
    <p>拖拽窗口调整大小,观察下方的触发次数差异</p>
    
    <div style="display: flex; gap: 20px; margin-top: 20px;">
        <div style="flex: 1; padding: 15px; background-color: #ffe6e6; border-radius: 5px;">
            <h4>普通监听</h4>
            <p id="normalCount">触发次数: 0</p>
        </div>
        <div style="flex: 1; padding: 15px; background-color: #e6ffe6; border-radius: 5px;">
            <h4>防抖监听(300ms)</h4>
            <p id="debounceCount">触发次数: 0</p>
        </div>
    </div>

    <script>
        let normalCounter = 0;
        let debounceCounter = 0;
        let normalDisplay = document.getElementById("normalCount");
        let debounceDisplay = document.getElementById("debounceCount");
        
        // 普通监听:每次 resize 都触发
        function normalResize() {
            normalCounter++;
            normalDisplay.innerHTML = `触发次数: ${normalCounter}`;
        }
        
        // 防抖函数
        function debounce(func, delay) {
            let timer;
            return function() {
                clearTimeout(timer);
                timer = setTimeout(() => {
                    func.apply(this, arguments);
                }, delay);
            };
        }
        
        // 防抖处理的函数
        function debouncedResize() {
            debounceCounter++;
            debounceDisplay.innerHTML = `触发次数: ${debounceCounter}`;
        }
        
        window.addEventListener("resize", normalResize);
        window.addEventListener("resize", debounce(debouncedResize, 300));
        
        // 初始化显示
        normalDisplay.innerHTML = `触发次数: ${normalCounter}`;
        debounceDisplay.innerHTML = `触发次数: ${debounceCounter}`;
    </script>
</body>
</html>

说明:防抖的原理是:在事件连续触发时,只执行之后一次。拖拽窗口时,普通监听会触发几十次甚至上百次,而防抖后的监听只在停止调整后执行一次。这能有效减少不必要的计算,提升页面性能。

本节课程知识要点

  1. resize 的触发时机:当浏览器窗口尺寸变化时触发,包括拖拽边缘、较大化/小化、设备旋转等。频繁触发是它的特性,需要配合防抖或节流优化。

  2. 尺寸获取属性

    • innerWidth/innerHeight:视口尺寸(最常用)

    • outerWidth/outerHeight:浏览器窗口整体尺寸

    • clientWidth/clientHeight:元素内容区域尺寸(不含边框)

    • offsetWidth/offsetHeight:元素布局尺寸(含边框)

  3. 三种绑定方式:HTML 属性、DOM 属性、addEventListener。推荐使用 addEventListener,因为它支持多事件绑定且易于维护。

  4. 性能优化resize 事件触发频率高,建议配合防抖(debounce)或节流(throttle)使用,避免在每次触发时都执行重计算操作。

  5. 常见应用场景

    • 响应式布局的实时适配

    • 图表、地图等组件的重新渲染

    • 动态调整字体大小或元素尺寸

    • 根据窗口尺寸显示/隐藏特定模块

  6. 注意事项:在移动端,设备旋转也会触发 resize 事件,开发时需要考虑移动端的适配。在 resize 事件中频繁操作 DOM 可能引起性能问题,尽量只做必要的数据更新。

← JavaScript onload事件 没有下一篇了 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号