refactor: 重构加载动画代码,提升可维护性
JavaScript 重构: - 创建 LoadingOverlay 模块化管理器(IIFE 模式) - 封装元素创建、显示、隐藏和销毁逻辑 - 添加定时器管理,防止内存泄漏 - 提供向后兼容的函数接口 - 使用常量管理配置项(ID、类名、动画时长) - 改进代码注释和 JSDoc 文档 CSS 重构: - 统一类名前缀为 loading-*,语义更清晰 - 移除 ID 选择器依赖,改用类选择器 - 分离关注点:基础旋转器、进度条、遮罩层、骨架屏 - 添加结构化注释,便于定位和修改 - 优化选择器层级,提升性能 - 独立动画关键帧定义 代码改进: - 减少重复代码,提高复用性 - 更好的错误处理和边界情况处理 - 支持多次调用不会重复创建元素 - 清晰的模块边界和职责划分
This commit is contained in:
190
argontheme.js
190
argontheme.js
@@ -3199,73 +3199,167 @@ var pjaxContainers = pjaxContainerSelectors.filter(function(selector) {
|
||||
return document.querySelector(selector);
|
||||
});
|
||||
|
||||
// ==========================================================================
|
||||
// 页面加载动画管理器
|
||||
// ==========================================================================
|
||||
|
||||
/**
|
||||
* 显示页面加载动画遮罩
|
||||
* 加载动画管理器
|
||||
* 负责创建、显示和隐藏页面加载动画
|
||||
*/
|
||||
function showLoadingOverlay() {
|
||||
let el = document.getElementById('article-loading-overlay');
|
||||
if (!el) {
|
||||
// 动态创建加载动画元素
|
||||
el = document.createElement('div');
|
||||
el.id = 'article-loading-overlay';
|
||||
el.innerHTML = `
|
||||
<div class="overlay-content">
|
||||
<div class="overlay-card">
|
||||
<div class="overlay-thumb skeleton">
|
||||
<div class="overlay-thumb-shimmer"></div>
|
||||
const LoadingOverlay = (function() {
|
||||
const OVERLAY_ID = 'article-loading-overlay';
|
||||
const ANIMATION_DURATION = 300;
|
||||
const CLASS_VISIBLE = 'is-visible';
|
||||
const CLASS_HIDING = 'is-hiding';
|
||||
|
||||
let overlayElement = null;
|
||||
let hideTimer = null;
|
||||
|
||||
/**
|
||||
* 创建骨架屏 HTML 结构
|
||||
* @returns {string} HTML 字符串
|
||||
*/
|
||||
function createSkeletonHTML() {
|
||||
return `
|
||||
<div class="loading-overlay-content">
|
||||
<div class="loading-card">
|
||||
<div class="loading-thumb">
|
||||
<div class="loading-shimmer"></div>
|
||||
</div>
|
||||
<div class="overlay-body">
|
||||
<div class="overlay-meta">
|
||||
<div class="overlay-avatar skeleton"></div>
|
||||
<div class="overlay-meta-text">
|
||||
<div class="overlay-meta-line skeleton" style="width: 120px"></div>
|
||||
<div class="overlay-meta-line skeleton" style="width: 80px"></div>
|
||||
<div class="loading-body">
|
||||
<div class="loading-meta">
|
||||
<div class="loading-avatar"></div>
|
||||
<div class="loading-meta-text">
|
||||
<div class="loading-meta-line" style="width: 120px"></div>
|
||||
<div class="loading-meta-line" style="width: 80px"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overlay-title skeleton"></div>
|
||||
<div class="overlay-text">
|
||||
<div class="overlay-row skeleton" style="width: 95%"></div>
|
||||
<div class="overlay-row skeleton" style="width: 88%"></div>
|
||||
<div class="overlay-row skeleton" style="width: 92%"></div>
|
||||
<div class="overlay-row skeleton" style="width: 78%"></div>
|
||||
<div class="loading-title"></div>
|
||||
<div class="loading-text">
|
||||
<div class="loading-line" style="width: 95%"></div>
|
||||
<div class="loading-line" style="width: 88%"></div>
|
||||
<div class="loading-line" style="width: 92%"></div>
|
||||
<div class="loading-line" style="width: 78%"></div>
|
||||
</div>
|
||||
<div class="overlay-tags">
|
||||
<div class="overlay-tag skeleton"></div>
|
||||
<div class="overlay-tag skeleton"></div>
|
||||
<div class="overlay-tag skeleton"></div>
|
||||
<div class="loading-tags">
|
||||
<div class="loading-tag"></div>
|
||||
<div class="loading-tag"></div>
|
||||
<div class="loading-tag"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overlay-spinner">
|
||||
<div class="spinner-ring">
|
||||
<div class="spinner-ring-inner"></div>
|
||||
<div class="loading-spinner-wrapper">
|
||||
<div class="loading-spinner">
|
||||
<div class="loading-spinner-ring"></div>
|
||||
</div>
|
||||
<div class="spinner-text">正在加载精彩内容</div>
|
||||
<div class="spinner-dots">
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<span class="dot"></span>
|
||||
<div class="loading-text-hint">正在加载精彩内容</div>
|
||||
<div class="loading-dots">
|
||||
<span class="loading-dot"></span>
|
||||
<span class="loading-dot"></span>
|
||||
<span class="loading-dot"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
document.body.appendChild(el);
|
||||
}
|
||||
el.classList.remove('is-hiding');
|
||||
el.classList.add('is-visible');
|
||||
|
||||
/**
|
||||
* 创建加载动画元素
|
||||
* @returns {HTMLElement} 创建的元素
|
||||
*/
|
||||
function createElement() {
|
||||
const el = document.createElement('div');
|
||||
el.id = OVERLAY_ID;
|
||||
el.className = 'loading-overlay';
|
||||
el.innerHTML = createSkeletonHTML();
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取或创建加载动画元素
|
||||
* @returns {HTMLElement} 加载动画元素
|
||||
*/
|
||||
function getElement() {
|
||||
if (!overlayElement) {
|
||||
overlayElement = document.getElementById(OVERLAY_ID);
|
||||
}
|
||||
if (!overlayElement) {
|
||||
overlayElement = createElement();
|
||||
document.body.appendChild(overlayElement);
|
||||
}
|
||||
return overlayElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示加载动画
|
||||
*/
|
||||
function show() {
|
||||
// 清除可能存在的隐藏定时器
|
||||
if (hideTimer) {
|
||||
clearTimeout(hideTimer);
|
||||
hideTimer = null;
|
||||
}
|
||||
|
||||
const el = getElement();
|
||||
el.classList.remove(CLASS_HIDING);
|
||||
|
||||
// 强制重排以确保动画生效
|
||||
void el.offsetWidth;
|
||||
|
||||
el.classList.add(CLASS_VISIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏加载动画
|
||||
*/
|
||||
function hide() {
|
||||
const el = document.getElementById(OVERLAY_ID);
|
||||
if (!el) return;
|
||||
|
||||
el.classList.add(CLASS_HIDING);
|
||||
|
||||
// 动画结束后清理状态
|
||||
hideTimer = setTimeout(function() {
|
||||
el.classList.remove(CLASS_VISIBLE, CLASS_HIDING);
|
||||
hideTimer = null;
|
||||
}, ANIMATION_DURATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁加载动画元素
|
||||
*/
|
||||
function destroy() {
|
||||
if (hideTimer) {
|
||||
clearTimeout(hideTimer);
|
||||
hideTimer = null;
|
||||
}
|
||||
if (overlayElement && overlayElement.parentNode) {
|
||||
overlayElement.parentNode.removeChild(overlayElement);
|
||||
overlayElement = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 公开 API
|
||||
return {
|
||||
show: show,
|
||||
hide: hide,
|
||||
destroy: destroy
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* 显示页面加载动画(向后兼容)
|
||||
*/
|
||||
function showLoadingOverlay() {
|
||||
LoadingOverlay.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏页面加载动画遮罩
|
||||
* 隐藏页面加载动画(向后兼容)
|
||||
*/
|
||||
function hideLoadingOverlay() {
|
||||
let el = document.getElementById('article-loading-overlay');
|
||||
if (!el) return;
|
||||
el.classList.add('is-hiding');
|
||||
setTimeout(function() {
|
||||
el.classList.remove('is-visible');
|
||||
el.classList.remove('is-hiding');
|
||||
}, 300);
|
||||
LoadingOverlay.hide();
|
||||
}
|
||||
function startPageTransition() {
|
||||
document.documentElement.classList.add('page-transition-enter');
|
||||
@@ -3479,7 +3573,7 @@ $(document).on("click", ".reference-link , .reference-list-backlink" , function(
|
||||
}, 1);
|
||||
});
|
||||
|
||||
/*Tags Dialog pjax 加载后自动关闭/
|
||||
/*Tags Dialog pjax 加载后自动关闭 */
|
||||
$(document).on("click" , "#blog_tags .tag" , function(){
|
||||
$("#blog_tags button.close").trigger("click");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user