网页中的 loading 效果(加载动画)是一个非常常见且重要的用户体验元素,它的主要目的是在内容(如图片、数据、页面)完全加载完成前,给用户一个明确的反馈,告诉系统正在“努力工作”,从而减少用户的焦虑感,并营造一种专业和流畅的体验。

网页中的loading是怎么做的
(图片来源网络,侵删)

下面我将从 原理、实现方式、最佳实践 三个方面,详细为你讲解网页中的 loading 是怎么做的。


核心原理:控制可见性的时机

所有 loading 效果的核心原理都是的显示时机

  1. 显示 Loading 动画:在页面或内容开始加载的瞬间,立即显示一个 loading 动画。
  2. 隐藏 Loading 动画:在页面或内容完全加载完毕后,隐藏 loading 动画,并展示实际内容。

这个过程可以通过监听不同的事件来实现,具体取决于你要加载的是什么。


常见的实现方式

根据加载对象的不同,实现 loading 效果的方式也多种多样。

网页中的loading是怎么做的
(图片来源网络,侵删)

整页面加载

这是最基础的一种,用于页面从服务器获取 HTML 并完全渲染的过程。

  • 实现原理:监听 window 对象的 load 事件。load 事件在整个页面及其所有资源(如图片、CSS、JS 文件)都加载完毕后触发。
  • 如何实现
    1. <body> 标签开始处,放置一个全屏的 loading 动画遮罩层,并设置其 z-index 确保在最上层。
    2. 给这个遮罩层一个初始的 display: block;opacity: 1;
    3. <script> 标签中,监听 window.onload 事件,在事件触发后将遮罩层隐藏(display: none;opacity: 0;)。

示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">Page Loading</title>
    <style>
        /* Loading 遮罩层样式 */
        .page-loader {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: #fff; /* 背景色,与页面背景一致 */
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 9999; /* 确保在最上层 */
            transition: opacity 0.5s ease-out; /* 添加淡出效果 */
        }
        .page-loader.hidden {
            opacity: 0;
            pointer-events: none; /* 隐藏后不可交互 */
        }
        /* 简单的旋转动画 */
        .spinner {
            width: 50px;
            height: 50px;
            border: 5px solid #f3f3f3;
            border-top: 5px solid #3498db;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
    </style>
</head>
<body>
    <!-- Loading 遮罩层 -->
    <div class="page-loader" id="pageLoader">
        <div class="spinner"></div>
    </div>
    <!-- 页面实际内容 -->
    <h1>欢迎来到我的网站!</h1>
    <p>这里有很多内容...</p>
    <img src="https://via.placeholder.com/150" alt="Placeholder Image">
    <script>
        // 监听整个页面的 load 事件
        window.addEventListener('load', function() {
            // 页面加载完成后,隐藏 loader
            const loader = document.getElementById('pageLoader');
            loader.classList.add('hidden');
        });
    </script>
</body>
</html>

加载 (AJAX/Fetch)

这是现代 Web 开发中最常见的方式,例如点击“加载更多”按钮、从服务器获取数据并渲染到页面上。

  • 实现原理
    1. 用户触发一个操作(如点击按钮)。
    2. 显示 loading 动画(通常是一个图标或文字)。
    3. 使用 fetchXMLHttpRequest 发送异步请求。
    4. 在请求的 then (或 onload) 回调中,处理返回的数据并渲染到页面上。
    5. finally (或 onload/onerror) 回调中,无论成功失败,都隐藏 loading 动画。

示例代码 (使用 Fetch API):

网页中的loading是怎么做的
(图片来源网络,侵删)
<button id="loadDataBtn">加载数据</button>
<div id="dataContainer"></div>
<div id="ajaxLoader" style="display: none;">加载中...</div>
<script>
    const loadBtn = document.getElementById('loadDataBtn');
    const dataContainer = document.getElementById('dataContainer');
    const ajaxLoader = document.getElementById('ajaxLoader');
    loadBtn.addEventListener('click', function() {
        // 1. 显示 loading
        ajaxLoader.style.display = 'block';
        dataContainer.innerHTML = ''; // 清空旧数据
        // 2. 发起异步请求
        fetch('https://jsonplaceholder.typicode.com/posts/1')
            .then(response => response.json())
            .then(data => {
                // 3. 请求成功,渲染数据
                dataContainer.innerHTML = `<h2>${data.title}</h2><p>${data.body}</p>`;
            })
            .catch(error => {
                console.error('请求失败:', error);
                dataContainer.innerHTML = '<p>加载失败,请重试。</p>';
            })
            .finally(() => {
                // 4. 无论成功失败,都隐藏 loading
                ajaxLoader.style.display = 'none';
            });
    });
</script>

图片懒加载

对于包含大量图片的页面,懒加载可以显著提升初始加载速度,loading 效果通常用在图片即将进入视口时。

  • 实现原理
    1. <img> 标签中,不直接设置 src 属性,而是设置一个占位图或背景色到 src,并将真实图片的 URL 存放在 data-src 属性中。
    2. 使用 IntersectionObserver API 来检测图片元素是否进入用户的可视区域(Viewport)。
    3. 当图片进入视口时,将 data-src 的值赋给 src 属性,浏览器开始加载图片。
    4. 在图片加载过程中,可以显示一个 loading 动画(一个灰色背景或骨架屏)。

示例代码:

<style>
    .lazy-img {
        width: 300px;
        height: 200px;
        background-color: #f0f0f0; /* 占位背景色 */
        display: block;
    }
</style>
<img class="lazy-img" data-src="https://picsum.photos/300/200?random=1" alt="Lazy Image 1">
<img class="lazy-img" data-src="https://picsum.photos/300/200?random=2" alt="Lazy Image 2">
<img class="lazy-img" data-src="https://picsum.photos/300/200?random=3" alt="Lazy Image 3">
<script>
    document.addEventListener("DOMContentLoaded", function() {
        const lazyImages = document.querySelectorAll('img.lazy-img');
        if ('IntersectionObserver' in window) {
            const imageObserver = new IntersectionObserver((entries, observer) => {
                entries.forEach(entry => {
                    // 如果图片进入视口
                    if (entry.isIntersecting) {
                        const img = entry.target;
                        const src = img.getAttribute('data-src');
                        // 设置 src 开始加载
                        img.src = src;
                        img.classList.remove('lazy-img'); // 移除占位样式类
                        // 图片加载完成后,停止观察
                        img.onload = () => {
                            observer.unobserve(img);
                        };
                    }
                });
            });
            // 开始观察所有懒加载图片
            lazyImages.forEach(img => {
                imageObserver.observe(img);
            });
        } else {
            // 降级处理:对于不支持 IntersectionObserver 的浏览器
            // 可以使用 scroll 事件监听等方式
            console.log("浏览器不支持 IntersectionObserver");
        }
    });
</script>

Loading 动画的类型和最佳实践

Loading 效果本身也有很多种形式,选择合适的类型至关重要。

常见的动画类型

  • 旋转加载器:最经典、最通用的类型,适用于大多数场景。
  • 骨架屏加载完成前,先显示一个与最终布局相似的灰色占位框,这能给用户一个很好的预期,感知到内容的结构和加载进度,常用于新闻列表、商品列表等。
  • 进度条:当可以预估加载时间时(如文件上传、视频缓冲),进度条是最佳选择,因为它能提供最明确的进度反馈。
  • 涟漪/脉冲效果:更现代、更轻量的设计,通常用于按钮点击或小模块的加载反馈。
  • 自定义动画:结合品牌特色的有趣动画,能提升品牌记忆点,但要注意不要过于花哨分散用户注意力。

最佳实践

  • 明确告知用户:Loading 动画必须清晰可见,让用户一眼就知道系统正在响应。
  • 提供反馈:除了动画,文字提示如“加载中...”、“正在保存...”也非常有效。
  • 控制时长:如果加载时间超过几秒钟,考虑提供取消操作的选项或更详细的进度说明。
  • 不要滥用:只在真正需要等待的时候显示,对于瞬间就能完成的后台操作,可能不需要 loading 动画。
  • 性能优化:Loading 动画本身不能成为性能瓶颈,避免使用过于复杂的 CSS 动画或大量 JavaScript 计算,尤其是在页面首次加载时。
  • 无障碍性:为 loading 状态添加 ARIA 属性,如 aria-live="polite",以便屏幕阅读器可以通知视障用户内容正在更新。

网页中的 loading 效果是一个系统工程,它结合了 HTML 结构、CSS 样式/动画 和 JavaScript 逻辑

  1. 原理:通过控制内容的显示与隐藏来管理用户预期。
  2. 实现:根据加载对象(整页面、异步数据、图片)选择不同的事件监听方法(window.onload, fetch().finally(), IntersectionObserver)。
  3. 设计:根据场景选择合适的动画类型(旋转器、骨架屏、进度条),并遵循最佳实践,以提供最佳的用户体验。