下面我将从前端实现和后端集成两个方面,为您提供几种常用且效果出色的代码示例和实现思路。
核心思想
无论使用哪种效果,其基本原理都是一样的:
- 触发加载状态:当用户执行一个操作(如点击按钮、提交表单、发起AJAX请求)时,通过 JavaScript 显示一个加载动画。
- 隐藏加载状态:当后端处理完成,返回响应后,通过 JavaScript 隐藏加载动画。
简单的全屏遮罩加载动画 (推荐)
这是最常用、最直观的方式,通常是一个半透明的遮罩层覆盖在整个页面上,中间有一个旋转的图标。
创建加载遮罩组件 (Partial View)
在 Views/Shared 文件夹下创建一个名为 _LoadingPartial.cshtml 的文件。
<!-- Views/Shared/_LoadingPartial.cshtml -->
@*
这个部分视图将作为加载遮罩。
默认是隐藏的,通过 JavaScript 类来控制其显示和隐藏。
*@
<div id="loadingOverlay" class="loading-overlay">
<div class="spinner"></div>
<p>正在加载,请稍候...</p>
</div>
添加 CSS 样式
在 wwwroot/css/site.css (或你自定义的CSS文件) 中添加以下样式:
/* wwwroot/css/site.css */
/* 加载遮罩层样式 */
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5); /* 半透明黑色背景 */
display: flex; /* 使用 flexbox 居中内容 */
justify-content: center;
align-items: center;
z-index: 9999; /* 确保它在最上层 */
color: white;
font-size: 1.2em;
}
/* 默认隐藏加载遮罩 */
.loading-overlay.hidden {
display: none;
}
/* 旋转的加载动画 (spinner) */
.spinner {
border: 5px solid #f3f3f3; /* Light grey */
border-top: 5px solid #3498db; /* Blue */
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
margin-bottom: 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
在布局文件中引入遮罩和 JavaScript
在 Views/Shared/_Layout.cshtml 文件中,将 _LoadingPartial.cshtml 和控制它的 JavaScript 代码放进去。
<!-- Views/Shared/_Layout.cshtml -->
...
<body>
@* 在 body 的开头或结尾引入加载遮罩 *@
@await Html.PartialAsync("_LoadingPartial")
<header>...</header>
<div class="container">...</div>
<footer>...</footer>
@* 在页面底部引入你的 JS 文件,或者直接在这里写脚本 *@
<script>
// 显示加载遮罩的函数
function showLoading() {
document.getElementById('loadingOverlay').classList.remove('hidden');
}
// 隐藏加载遮罩的函数
function hideLoading() {
document.getElementById('loadingOverlay').classList.add('hidden');
}
// === 1. 页面首次加载时显示加载效果 ===
// 当整个页面文档加载完成后执行
document.addEventListener('DOMContentLoaded', function () {
// 页面加载完成后,我们希望在很短的延迟后立即显示遮罩,
// 然后它会在主要资源(如图片)加载完成后自动隐藏。
// 但更常见的做法是只在AJAX请求时显示。
// 如果非要页面加载时显示,可以这样:
showLoading();
});
// 当整个页面(包括图片、脚本等所有资源)完全加载后,隐藏遮罩
window.addEventListener('load', function () {
hideLoading();
});
// === 2. 为所有 AJAX 请求自动添加加载效果 (推荐) ===
// 使用 jQuery 的 ajaxSetup 来全局配置
// 如果你使用的是原生 JavaScript,可以使用 fetch API 的拦截器
$(document).ajaxStart(function () {
showLoading();
}).ajaxStop(function () {
hideLoading();
});
// 如果你使用原生 Fetch API
// const originalFetch = window.fetch;
// window.fetch = async function (...args) {
// showLoading();
// try {
// const response = await originalFetch.apply(this, args);
// return response;
// } finally {
// hideLoading();
// }
// };
</script>
</body>
在表单提交或 AJAX 请求中使用
当你提交一个表单或发起 AJAX 请求时,ajaxStart 和 ajaxStop 事件会自动触发,加载遮罩会自动显示和隐藏。
示例:表单提交
<form asp-action="Create" asp-controller="Home" method="post" id="myForm">
<input type="text" name="name" placeholder="输入名称" />
<button type="submit">提交</button>
</form>
当你点击提交按钮时,表单会提交,同时加载遮罩会显示,直到服务器返回响应并页面刷新(或部分刷新)。
示例:使用 jQuery 发起 AJAX 请求
$.ajax({
url: '/api/data',
type: 'GET',
success: function (data) {
console.log('数据加载成功:', data);
// 在这里处理返回的数据
},
error: function (error) {
console.error('数据加载失败:', error);
}
// 不需要在这里手动调用 showLoading/hideLoading,
// 因为全局的 ajaxStart/Stop 已经处理了
});
使用现成的 UI 框架 (如 Bootstrap)
如果你已经在使用 Bootstrap,可以利用它的组件和 JavaScript 来实现更美观的效果。
修改 _LoadingPartial.cshtml
<!-- Views/Shared/_LoadingPartial.cshtml -->
@*
使用 Bootstrap 的 Modal 组件作为加载遮罩
*@
<div class="modal fade" id="loadingModal" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static" data-keyboard="false">
<div class="modal-dialog modal-sm modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-body text-center">
<div class="spinner-border text-primary" role="status">
<span class="sr-only">Loading...</span>
</div>
<p class="mt-2">正在加载,请稍候...</p>
</div>
</div>
</div>
</div>
修改 _Layout.cshtml 中的 JavaScript
<!-- Views/Shared/_Layout.cshtml -->
...
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script>
// 显示加载模态框
function showLoading() {
$('#loadingModal').modal('show');
}
// 隐藏加载模态框
function hideLoading() {
$('#loadingModal').modal('hide');
}
// === 为 AJAX 请求自动添加加载效果 ===
$(document).ajaxStart(function () {
showLoading();
}).ajaxStop(function () {
hideLoading();
});
// === 页面首次加载时显示加载效果 ===
document.addEventListener('DOMContentLoaded', function () {
showLoading();
});
window.addEventListener('load', function () {
hideLoading();
});
</script>
这种方式的好处是与 Bootstrap 的视觉风格完全统一,且模态框可以阻止用户在加载时与页面交互(data-backdrop="static")。
页面内局部加载效果
有时你不需要全屏遮罩,只需要在某个按钮或表格旁边显示一个加载图标。
HTML 结构
<button id="loadDataBtn" class="btn btn-primary">
<span class="spinner-border spinner-border-sm d-none" id="btnSpinner" role="status" aria-hidden="true"></span>
加载数据
</button>
<div id="dataContainer">
<!-- 数据将在这里显示 -->
</div>
JavaScript 代码
<script>
document.getElementById('loadDataBtn').addEventListener('click', function() {
const btn = this;
const spinner = document.getElementById('btnSpinner');
const container = document.getElementById('dataContainer');
// 1. 禁用按钮,显示加载图标
btn.disabled = true;
spinner.classList.remove('d-none');
// 2. 模拟 AJAX 请求
fetch('/api/data')
.then(response => response.json())
.then(data => {
// 3. 请求成功,处理数据
container.innerHTML = '<p>数据加载成功: ' + JSON.stringify(data) + '</p>';
})
.catch(error => {
// 4. 请求失败,显示错误信息
container.innerHTML = '<p class="text-danger">加载数据失败。</p>';
console.error('Error:', error);
})
.finally(() => {
// 5. 无论成功失败,都恢复按钮状态
btn.disabled = false;
spinner.classList.add('d-none');
});
});
</script>
总结与选择建议
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 全屏遮罩 | 用户体验好,明确告知用户系统正在处理;实现简单,可全局复用。 | 会阻止用户与整个页面的交互。 | 表单提交、页面跳转、数据量大的AJAX请求,这是最通用和推荐的首选方案。 |
| Bootstrap Modal | 视觉风格统一,美观;可配置性强(如阻止交互)。 | 依赖 Bootstrap 框架。 | 已经在使用 Bootstrap 的项目中,希望获得更精致效果的场景。 |
| 局部加载 | 交互友好,不影响页面其他部分;轻量。 | 只能指示局部操作的状态。 | 按钮点击后更新局部数据、分页加载等不希望中断用户当前操作的场景。 |
对于大多数 .NET Web 应用,方案一(全屏遮罩) 结合 全局 AJAX 拦截 是最实用、最有效的解决方案,你可以根据具体需求,灵活组合或修改这些方案。
