feat: 实现统一的资源清理管理器
- 封装 cleanupPjaxResources() 函数,统一管理所有资源清理 - 添加 cleanupLazyloadObserver() - 清理 Lazyload Observer - 添加 cleanupZoomifyInstances() - 清理 Zoomify 实例 - 添加 cleanupTippyInstances() - 清理 Tippy 实例 - 添加 cleanupMermaidInstances() - 清理 Mermaid 实例和事件监听器 - 添加 cleanupDynamicStyles() - 清理动态 style 标签 - 添加 cleanupDynamicScripts() - 清理动态 script 标签 - 添加 cleanupEventListeners() - 清理事件监听器 - 每个清理函数都包含错误处理和调试日志 - 满足需求 1.1-1.4, 2.3, 6.1
This commit is contained in:
170
argontheme.js
170
argontheme.js
@@ -2732,47 +2732,199 @@ if ($("html").hasClass("banner-as-cover")){
|
|||||||
/*Pjax*/
|
/*Pjax*/
|
||||||
var pjaxScrollTop = 0, pjaxLoading = false;
|
var pjaxScrollTop = 0, pjaxLoading = false;
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// 统一的资源清理管理器
|
||||||
|
// ==========================================================================
|
||||||
|
// 在 PJAX 页面切换时清理所有旧页面资源,避免内存泄漏和功能失效
|
||||||
|
// Validates: Requirements 1.1, 1.2, 1.3, 1.4, 2.3, 6.1
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清理 PJAX 页面切换前的所有资源
|
* 清理 Lazyload Observer
|
||||||
* 包括 LazyLoad Observer、Zoomify 实例、Tippy 实例
|
* @returns {void}
|
||||||
* 在 pjax:beforeReplace 事件中调用
|
|
||||||
*/
|
*/
|
||||||
function cleanupPjaxResources() {
|
function cleanupLazyloadObserver() {
|
||||||
// 清理 LazyLoad Observer
|
|
||||||
if (lazyloadObserver) {
|
if (lazyloadObserver) {
|
||||||
|
try {
|
||||||
lazyloadObserver.disconnect();
|
lazyloadObserver.disconnect();
|
||||||
lazyloadObserver = null;
|
lazyloadObserver = null;
|
||||||
|
ArgonDebug.log('Lazyload Observer 已清理');
|
||||||
|
} catch(e) {
|
||||||
|
ArgonDebug.warn('清理 Lazyload Observer 失败:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清理 Zoomify 实例
|
/**
|
||||||
|
* 清理 Zoomify 实例
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function cleanupZoomifyInstances() {
|
||||||
if (zoomifyInstances && zoomifyInstances.length > 0) {
|
if (zoomifyInstances && zoomifyInstances.length > 0) {
|
||||||
|
let cleanedCount = 0;
|
||||||
zoomifyInstances.forEach(function(instance) {
|
zoomifyInstances.forEach(function(instance) {
|
||||||
try {
|
try {
|
||||||
if (instance && typeof instance.destroy === 'function') {
|
if (instance && typeof instance.destroy === 'function') {
|
||||||
instance.destroy();
|
instance.destroy();
|
||||||
|
cleanedCount++;
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
ArgonDebug.warn('Failed to destroy Zoomify instance:', e);
|
ArgonDebug.warn('销毁 Zoomify 实例失败:', e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
zoomifyInstances = [];
|
zoomifyInstances = [];
|
||||||
|
ArgonDebug.log(`已清理 ${cleanedCount} 个 Zoomify 实例`);
|
||||||
}
|
}
|
||||||
|
// 移除初始化标记
|
||||||
$('img.zoomify-initialized').removeClass('zoomify-initialized');
|
$('img.zoomify-initialized').removeClass('zoomify-initialized');
|
||||||
|
}
|
||||||
|
|
||||||
// 清理 Tippy 实例
|
/**
|
||||||
|
* 清理 Tippy 实例
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function cleanupTippyInstances() {
|
||||||
if (typeof tippy !== 'undefined') {
|
if (typeof tippy !== 'undefined') {
|
||||||
|
let cleanedCount = 0;
|
||||||
document.querySelectorAll('[data-tippy-root]').forEach(function(el) {
|
document.querySelectorAll('[data-tippy-root]').forEach(function(el) {
|
||||||
try {
|
try {
|
||||||
if (el._tippy && typeof el._tippy.destroy === 'function') {
|
if (el._tippy && typeof el._tippy.destroy === 'function') {
|
||||||
el._tippy.destroy();
|
el._tippy.destroy();
|
||||||
|
cleanedCount++;
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
ArgonDebug.warn('Failed to destroy Tippy instance:', e);
|
ArgonDebug.warn('销毁 Tippy 实例失败:', e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$('.tippy-initialized').removeClass('tippy-initialized');
|
$('.tippy-initialized').removeClass('tippy-initialized');
|
||||||
|
if (cleanedCount > 0) {
|
||||||
|
ArgonDebug.log(`已清理 ${cleanedCount} 个 Tippy 实例`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理 Mermaid 实例
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function cleanupMermaidInstances() {
|
||||||
|
try {
|
||||||
|
// 清理已渲染的图表记录
|
||||||
|
if (typeof MermaidRenderer !== 'undefined' && MermaidRenderer.rendered) {
|
||||||
|
const count = MermaidRenderer.rendered.size;
|
||||||
|
MermaidRenderer.rendered.clear();
|
||||||
|
if (count > 0) {
|
||||||
|
ArgonDebug.log(`已清理 ${count} 个 Mermaid 图表记录`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除 Mermaid 容器的事件监听器
|
||||||
|
document.querySelectorAll('.mermaid-container').forEach(function(container) {
|
||||||
|
// 移除工具栏事件监听器
|
||||||
|
const toolbar = container.querySelector('.mermaid-toolbar');
|
||||||
|
if (toolbar) {
|
||||||
|
// 克隆节点以移除所有事件监听器
|
||||||
|
const newToolbar = toolbar.cloneNode(true);
|
||||||
|
toolbar.parentNode.replaceChild(newToolbar, toolbar);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ArgonDebug.log('Mermaid 实例已清理');
|
||||||
|
} catch(e) {
|
||||||
|
ArgonDebug.warn('清理 Mermaid 实例失败:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理动态添加的 style 标签
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function cleanupDynamicStyles() {
|
||||||
|
try {
|
||||||
|
// 只清理标记为动态的样式
|
||||||
|
const dynamicStyles = document.querySelectorAll('style[data-dynamic="true"]');
|
||||||
|
if (dynamicStyles.length > 0) {
|
||||||
|
dynamicStyles.forEach(function(style) {
|
||||||
|
style.remove();
|
||||||
|
});
|
||||||
|
ArgonDebug.log(`已清理 ${dynamicStyles.length} 个动态样式`);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
ArgonDebug.warn('清理动态样式失败:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理动态添加的 script 标签
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function cleanupDynamicScripts() {
|
||||||
|
try {
|
||||||
|
// 只清理标记为动态的脚本
|
||||||
|
const dynamicScripts = document.querySelectorAll('script[data-dynamic="true"]');
|
||||||
|
if (dynamicScripts.length > 0) {
|
||||||
|
dynamicScripts.forEach(function(script) {
|
||||||
|
script.remove();
|
||||||
|
});
|
||||||
|
ArgonDebug.log(`已清理 ${dynamicScripts.length} 个动态脚本`);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
ArgonDebug.warn('清理动态脚本失败:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理事件监听器
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function cleanupEventListeners() {
|
||||||
|
try {
|
||||||
|
// 清理 Mermaid 相关的事件监听器
|
||||||
|
// 注意:大部分事件使用事件委托,不需要手动清理
|
||||||
|
// 这里只清理特定的非委托事件
|
||||||
|
|
||||||
|
// 清理滚动监听(如果使用了降级方案)
|
||||||
|
if (typeof lazyloadScrollHandler !== 'undefined') {
|
||||||
|
window.removeEventListener('scroll', lazyloadScrollHandler);
|
||||||
|
window.removeEventListener('resize', lazyloadScrollHandler);
|
||||||
|
ArgonDebug.log('已清理 Lazyload 滚动监听器');
|
||||||
|
}
|
||||||
|
|
||||||
|
ArgonDebug.log('事件监听器已清理');
|
||||||
|
} catch(e) {
|
||||||
|
ArgonDebug.warn('清理事件监听器失败:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理 PJAX 页面切换前的所有资源
|
||||||
|
* 统一的资源清理管理器,在 pjax:beforeReplace 事件中调用
|
||||||
|
*
|
||||||
|
* 清理内容包括:
|
||||||
|
* - Lazyload Observer
|
||||||
|
* - Zoomify 实例
|
||||||
|
* - Tippy 实例
|
||||||
|
* - Mermaid 实例
|
||||||
|
* - 动态 style 标签
|
||||||
|
* - 动态 script 标签
|
||||||
|
* - 事件监听器
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function cleanupPjaxResources() {
|
||||||
|
ArgonDebug.log('开始清理 PJAX 资源...');
|
||||||
|
|
||||||
|
// 按顺序清理各类资源
|
||||||
|
cleanupLazyloadObserver();
|
||||||
|
cleanupZoomifyInstances();
|
||||||
|
cleanupTippyInstances();
|
||||||
|
cleanupMermaidInstances();
|
||||||
|
cleanupDynamicStyles();
|
||||||
|
cleanupDynamicScripts();
|
||||||
|
cleanupEventListeners();
|
||||||
|
|
||||||
|
ArgonDebug.log('PJAX 资源清理完成');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置 GT4 验证码
|
* 重置 GT4 验证码
|
||||||
|
|||||||
Reference in New Issue
Block a user