From 8180a87b899f3e49f4d7a6d7f86f2c6da6542bf1 Mon Sep 17 00:00:00 2001 From: nanhaoluo <3075912108@qq.com> Date: Sun, 25 Jan 2026 00:20:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E7=9A=84=E8=B5=84=E6=BA=90=E6=B8=85=E7=90=86=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 封装 cleanupPjaxResources() 函数,统一管理所有资源清理 - 添加 cleanupLazyloadObserver() - 清理 Lazyload Observer - 添加 cleanupZoomifyInstances() - 清理 Zoomify 实例 - 添加 cleanupTippyInstances() - 清理 Tippy 实例 - 添加 cleanupMermaidInstances() - 清理 Mermaid 实例和事件监听器 - 添加 cleanupDynamicStyles() - 清理动态 style 标签 - 添加 cleanupDynamicScripts() - 清理动态 script 标签 - 添加 cleanupEventListeners() - 清理事件监听器 - 每个清理函数都包含错误处理和调试日志 - 满足需求 1.1-1.4, 2.3, 6.1 --- argontheme.js | 178 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 165 insertions(+), 13 deletions(-) diff --git a/argontheme.js b/argontheme.js index 37959bc..78087de 100644 --- a/argontheme.js +++ b/argontheme.js @@ -2732,48 +2732,200 @@ if ($("html").hasClass("banner-as-cover")){ /*Pjax*/ var pjaxScrollTop = 0, pjaxLoading = false; +// ========================================================================== +// 统一的资源清理管理器 +// ========================================================================== +// 在 PJAX 页面切换时清理所有旧页面资源,避免内存泄漏和功能失效 +// Validates: Requirements 1.1, 1.2, 1.3, 1.4, 2.3, 6.1 +// ========================================================================== + /** - * 清理 PJAX 页面切换前的所有资源 - * 包括 LazyLoad Observer、Zoomify 实例、Tippy 实例 - * 在 pjax:beforeReplace 事件中调用 + * 清理 Lazyload Observer + * @returns {void} */ -function cleanupPjaxResources() { - // 清理 LazyLoad Observer +function cleanupLazyloadObserver() { if (lazyloadObserver) { - lazyloadObserver.disconnect(); - lazyloadObserver = null; + try { + lazyloadObserver.disconnect(); + lazyloadObserver = null; + ArgonDebug.log('Lazyload Observer 已清理'); + } catch(e) { + ArgonDebug.warn('清理 Lazyload Observer 失败:', e); + } } - - // 清理 Zoomify 实例 +} + +/** + * 清理 Zoomify 实例 + * @returns {void} + */ +function cleanupZoomifyInstances() { if (zoomifyInstances && zoomifyInstances.length > 0) { + let cleanedCount = 0; zoomifyInstances.forEach(function(instance) { try { if (instance && typeof instance.destroy === 'function') { instance.destroy(); + cleanedCount++; } } catch(e) { - ArgonDebug.warn('Failed to destroy Zoomify instance:', e); + ArgonDebug.warn('销毁 Zoomify 实例失败:', e); } }); zoomifyInstances = []; + ArgonDebug.log(`已清理 ${cleanedCount} 个 Zoomify 实例`); } + // 移除初始化标记 $('img.zoomify-initialized').removeClass('zoomify-initialized'); - - // 清理 Tippy 实例 +} + +/** + * 清理 Tippy 实例 + * @returns {void} + */ +function cleanupTippyInstances() { if (typeof tippy !== 'undefined') { + let cleanedCount = 0; document.querySelectorAll('[data-tippy-root]').forEach(function(el) { try { if (el._tippy && typeof el._tippy.destroy === 'function') { el._tippy.destroy(); + cleanedCount++; } } catch(e) { - ArgonDebug.warn('Failed to destroy Tippy instance:', e); + ArgonDebug.warn('销毁 Tippy 实例失败:', e); } }); $('.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 验证码 * 清理状态变量、隐藏字段和容器,然后重新初始化