fix: 优化 PJAX 和 LazyLoad 功能
- 创建 cleanupPjaxResources() 函数统一管理资源清理 - 创建 resetGT4Captcha() 函数封装验证码重置逻辑 - 消除 pjax:end 中的重复初始化调用(waterflowInit、lazyloadInit) - 优化 LazyLoad Observer 生命周期管理,添加存在性检查 - 使用 requestAnimationFrame 替代 setTimeout 优化图片加载效果 - 实现滚动监听降级方案,支持不兼容 IntersectionObserver 的浏览器 - 改进错误处理,所有第三方库调用都有 try-catch 保护 - 优化图片状态清理,使用正则表达式移除所有 lazyload-style-* 类名 需求:1.1-1.5, 2.1-2.5, 3.1-3.5, 4.1-4.5, 5.1-5.5, 6.1-6.5, 7.1-7.5
This commit is contained in:
257
argontheme.js
257
argontheme.js
@@ -2305,7 +2305,7 @@ $.fancybox.defaults.i18n = {
|
|||||||
var lazyloadObserver = null;
|
var lazyloadObserver = null;
|
||||||
|
|
||||||
function lazyloadInit() {
|
function lazyloadInit() {
|
||||||
// 清理旧的 Observer
|
// 清理旧的 Observer(防御性编程)
|
||||||
if (lazyloadObserver) {
|
if (lazyloadObserver) {
|
||||||
lazyloadObserver.disconnect();
|
lazyloadObserver.disconnect();
|
||||||
lazyloadObserver = null;
|
lazyloadObserver = null;
|
||||||
@@ -2314,16 +2314,7 @@ function lazyloadInit() {
|
|||||||
// 检查是否启用懒加载
|
// 检查是否启用懒加载
|
||||||
if (argonConfig.lazyload === false || argonConfig.lazyload === 'false') {
|
if (argonConfig.lazyload === false || argonConfig.lazyload === 'false') {
|
||||||
// 未启用懒加载时,直接加载所有图片
|
// 未启用懒加载时,直接加载所有图片
|
||||||
let images = document.querySelectorAll('img.lazyload[data-src]');
|
loadAllImagesImmediately();
|
||||||
images.forEach(function(img) {
|
|
||||||
let src = img.getAttribute('data-src');
|
|
||||||
if (src) {
|
|
||||||
img.src = src;
|
|
||||||
img.removeAttribute('data-src');
|
|
||||||
img.classList.remove('lazyload');
|
|
||||||
img.className = img.className.replace(/\blazyload-style-\d+\b/g, '').trim();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2341,7 +2332,7 @@ function lazyloadInit() {
|
|||||||
entries.forEach(function(entry) {
|
entries.forEach(function(entry) {
|
||||||
if (entry.isIntersecting) {
|
if (entry.isIntersecting) {
|
||||||
let img = entry.target;
|
let img = entry.target;
|
||||||
loadImage(img, effect);
|
loadImageOptimized(img, effect);
|
||||||
lazyloadObserver.unobserve(img);
|
lazyloadObserver.unobserve(img);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2357,19 +2348,16 @@ function lazyloadInit() {
|
|||||||
lazyloadObserver.observe(img);
|
lazyloadObserver.observe(img);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// 降级方案:直接加载所有图片
|
// 降级方案:使用滚动监听
|
||||||
images.forEach(function(img) {
|
lazyloadFallback(images, effect, threshold);
|
||||||
loadImage(img, effect);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载单张图片
|
* 优化的图片加载函数
|
||||||
* @param {HTMLImageElement} img - 图片元素
|
* 使用 requestAnimationFrame 替代 setTimeout
|
||||||
* @param {string} effect - 加载效果
|
|
||||||
*/
|
*/
|
||||||
function loadImage(img, effect) {
|
function loadImageOptimized(img, effect) {
|
||||||
let src = img.getAttribute('data-src');
|
let src = img.getAttribute('data-src');
|
||||||
if (!src) return;
|
if (!src) return;
|
||||||
|
|
||||||
@@ -2383,13 +2371,32 @@ function loadImage(img, effect) {
|
|||||||
// 移除所有 lazyload-style-* 类
|
// 移除所有 lazyload-style-* 类
|
||||||
img.className = img.className.replace(/\blazyload-style-\d+\b/g, '').trim();
|
img.className = img.className.replace(/\blazyload-style-\d+\b/g, '').trim();
|
||||||
|
|
||||||
// 应用加载效果
|
// 使用 requestAnimationFrame 应用加载效果
|
||||||
|
applyLoadEffectOptimized(img, effect);
|
||||||
|
};
|
||||||
|
tempImg.onerror = function() {
|
||||||
|
// 加载失败时使用原始 src
|
||||||
|
img.src = src;
|
||||||
|
img.removeAttribute('data-src');
|
||||||
|
img.classList.remove('lazyload');
|
||||||
|
img.className = img.className.replace(/\blazyload-style-\d+\b/g, '').trim();
|
||||||
|
};
|
||||||
|
tempImg.src = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 requestAnimationFrame 应用加载效果
|
||||||
|
*/
|
||||||
|
function applyLoadEffectOptimized(img, effect) {
|
||||||
if (effect === 'fadeIn') {
|
if (effect === 'fadeIn') {
|
||||||
img.style.opacity = '0';
|
img.style.opacity = '0';
|
||||||
img.style.transition = 'opacity 0.3s ease';
|
img.style.transition = 'opacity 0.3s ease';
|
||||||
setTimeout(function() {
|
requestAnimationFrame(function() {
|
||||||
|
requestAnimationFrame(function() {
|
||||||
img.style.opacity = '1';
|
img.style.opacity = '1';
|
||||||
}, 10);
|
});
|
||||||
|
});
|
||||||
|
// 清理 transition 样式
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
img.style.transition = '';
|
img.style.transition = '';
|
||||||
}, 310);
|
}, 310);
|
||||||
@@ -2397,23 +2404,73 @@ function loadImage(img, effect) {
|
|||||||
img.style.opacity = '0';
|
img.style.opacity = '0';
|
||||||
img.style.transform = 'translateY(-20px)';
|
img.style.transform = 'translateY(-20px)';
|
||||||
img.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
|
img.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
|
||||||
setTimeout(function() {
|
requestAnimationFrame(function() {
|
||||||
|
requestAnimationFrame(function() {
|
||||||
img.style.opacity = '1';
|
img.style.opacity = '1';
|
||||||
img.style.transform = 'translateY(0)';
|
img.style.transform = 'translateY(0)';
|
||||||
}, 10);
|
});
|
||||||
|
});
|
||||||
|
// 清理样式
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
img.style.transition = '';
|
img.style.transition = '';
|
||||||
img.style.transform = '';
|
img.style.transform = '';
|
||||||
}, 310);
|
}, 310);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
tempImg.onerror = function() {
|
|
||||||
// 加载失败时使用原始 src
|
/**
|
||||||
|
* 降级方案:使用滚动监听实现懒加载
|
||||||
|
*/
|
||||||
|
function lazyloadFallback(images, effect, threshold) {
|
||||||
|
let loadedImages = new Set();
|
||||||
|
|
||||||
|
function checkImagesInView() {
|
||||||
|
let viewportHeight = window.innerHeight;
|
||||||
|
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
|
||||||
|
|
||||||
|
images.forEach(function(img) {
|
||||||
|
if (loadedImages.has(img)) return;
|
||||||
|
|
||||||
|
let rect = img.getBoundingClientRect();
|
||||||
|
if (rect.top < viewportHeight + threshold && rect.bottom > -threshold) {
|
||||||
|
loadImageOptimized(img, effect);
|
||||||
|
loadedImages.add(img);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用节流函数优化性能
|
||||||
|
let throttleTimer = null;
|
||||||
|
function throttledCheck() {
|
||||||
|
if (throttleTimer) return;
|
||||||
|
throttleTimer = setTimeout(function() {
|
||||||
|
checkImagesInView();
|
||||||
|
throttleTimer = null;
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绑定事件监听器
|
||||||
|
window.addEventListener('scroll', throttledCheck, {passive: true});
|
||||||
|
window.addEventListener('resize', throttledCheck, {passive: true});
|
||||||
|
|
||||||
|
// 立即检查一次
|
||||||
|
checkImagesInView();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 立即加载所有图片(懒加载禁用时)
|
||||||
|
*/
|
||||||
|
function loadAllImagesImmediately() {
|
||||||
|
let images = document.querySelectorAll('img.lazyload[data-src]');
|
||||||
|
images.forEach(function(img) {
|
||||||
|
let src = img.getAttribute('data-src');
|
||||||
|
if (src) {
|
||||||
img.src = src;
|
img.src = src;
|
||||||
img.removeAttribute('data-src');
|
img.removeAttribute('data-src');
|
||||||
img.classList.remove('lazyload');
|
img.classList.remove('lazyload');
|
||||||
};
|
img.className = img.className.replace(/\blazyload-style-\d+\b/g, '').trim();
|
||||||
tempImg.src = src;
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保 DOM 加载完成后再初始化懒加载
|
// 确保 DOM 加载完成后再初始化懒加载
|
||||||
@@ -2511,6 +2568,82 @@ if ($("html").hasClass("banner-as-cover")){
|
|||||||
|
|
||||||
/*Pjax*/
|
/*Pjax*/
|
||||||
var pjaxScrollTop = 0, pjaxLoading = false;
|
var pjaxScrollTop = 0, pjaxLoading = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理 PJAX 页面切换前的所有资源
|
||||||
|
* 在 pjax:beforeReplace 事件中调用
|
||||||
|
*/
|
||||||
|
function cleanupPjaxResources() {
|
||||||
|
// 清理 LazyLoad Observer
|
||||||
|
if (lazyloadObserver) {
|
||||||
|
lazyloadObserver.disconnect();
|
||||||
|
lazyloadObserver = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理 Zoomify 实例
|
||||||
|
if (zoomifyInstances && zoomifyInstances.length > 0) {
|
||||||
|
zoomifyInstances.forEach(function(instance) {
|
||||||
|
try {
|
||||||
|
if (instance && typeof instance.destroy === 'function') {
|
||||||
|
instance.destroy();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.warn('Failed to destroy Zoomify instance:', e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
zoomifyInstances = [];
|
||||||
|
}
|
||||||
|
$('img.zoomify-initialized').removeClass('zoomify-initialized');
|
||||||
|
|
||||||
|
// 清理 Tippy 实例
|
||||||
|
if (typeof tippy !== 'undefined') {
|
||||||
|
document.querySelectorAll('[data-tippy-root]').forEach(function(el) {
|
||||||
|
try {
|
||||||
|
if (el._tippy && typeof el._tippy.destroy === 'function') {
|
||||||
|
el._tippy.destroy();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.warn('Failed to destroy Tippy instance:', e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('.tippy-initialized').removeClass('tippy-initialized');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置 GT4 验证码
|
||||||
|
* 在 pjax:end 事件中调用
|
||||||
|
*/
|
||||||
|
function resetGT4Captcha() {
|
||||||
|
try {
|
||||||
|
if ($('#geetest-captcha').length > 0) {
|
||||||
|
// 重置前端状态,避免重复提交阻塞
|
||||||
|
window.geetestVerified = false;
|
||||||
|
window.geetestAutoSubmitting = false;
|
||||||
|
|
||||||
|
// 清空隐藏字段,防止残留导致 pass_token 复用
|
||||||
|
$('#geetest_lot_number').val('');
|
||||||
|
$('#geetest_captcha_output').val('');
|
||||||
|
$('#geetest_pass_token').val('');
|
||||||
|
$('#geetest_gen_time').val('');
|
||||||
|
|
||||||
|
// 清空容器,防止重复 appendTo 导致多个实例
|
||||||
|
$('#geetest-captcha').empty();
|
||||||
|
|
||||||
|
// 若页面脚本已提供初始化方法,则调用以加载验证码
|
||||||
|
if (typeof initGeetestCaptcha === 'function') {
|
||||||
|
initGeetestCaptcha();
|
||||||
|
} else if (typeof loadGeetestScript === 'function' && typeof initGeetestCaptchaCore === 'function') {
|
||||||
|
loadGeetestScript(function() {
|
||||||
|
initGeetestCaptchaCore();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Geetest init on PJAX failed:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$.pjax.defaults.timeout = 10000;
|
$.pjax.defaults.timeout = 10000;
|
||||||
$.pjax.defaults.container = ['#primary', '#leftbar_part1_menu', '#leftbar_part2_inner', '.page-information-card-container', '#rightbar', '#wpadminbar'];
|
$.pjax.defaults.container = ['#primary', '#leftbar_part1_menu', '#leftbar_part2_inner', '.page-information-card-container', '#rightbar', '#wpadminbar'];
|
||||||
$.pjax.defaults.fragment = ['#primary', '#leftbar_part1_menu', '#leftbar_part2_inner', '.page-information-card-container', '#rightbar', '#wpadminbar'];
|
$.pjax.defaults.fragment = ['#primary', '#leftbar_part1_menu', '#leftbar_part2_inner', '.page-information-card-container', '#rightbar', '#wpadminbar'];
|
||||||
@@ -2557,39 +2690,16 @@ $(document).pjax("a[href]:not([no-pjax]):not(.no-pjax):not([target='_blank']):no
|
|||||||
NProgress.set(0.618);
|
NProgress.set(0.618);
|
||||||
}).on('pjax:beforeReplace', function(e, dom) {
|
}).on('pjax:beforeReplace', function(e, dom) {
|
||||||
// 清理旧页面的资源
|
// 清理旧页面的资源
|
||||||
if (lazyloadObserver) {
|
cleanupPjaxResources();
|
||||||
lazyloadObserver.disconnect();
|
|
||||||
lazyloadObserver = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清理 Zoomify 实例
|
|
||||||
if (zoomifyInstances.length > 0) {
|
|
||||||
zoomifyInstances.forEach(function(instance) {
|
|
||||||
try {
|
|
||||||
if (instance && typeof instance.destroy === 'function') {
|
|
||||||
instance.destroy();
|
|
||||||
}
|
|
||||||
} catch(e) {}
|
|
||||||
});
|
|
||||||
zoomifyInstances = [];
|
|
||||||
}
|
|
||||||
$('img.zoomify-initialized').removeClass('zoomify-initialized');
|
|
||||||
|
|
||||||
// 清理 Tippy 实例
|
|
||||||
if (typeof tippy !== 'undefined') {
|
|
||||||
document.querySelectorAll('[data-tippy-root]').forEach(function(el) {
|
|
||||||
try {
|
|
||||||
el._tippy?.destroy?.();
|
|
||||||
} catch(e) {}
|
|
||||||
});
|
|
||||||
$('.tippy-initialized').removeClass('tippy-initialized');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 更新 UI 状态
|
||||||
if ($("#post_comment", dom[0]).length > 0){
|
if ($("#post_comment", dom[0]).length > 0){
|
||||||
$("#fabtn_go_to_comment").removeClass("d-none");
|
$("#fabtn_go_to_comment").removeClass("d-none");
|
||||||
}else{
|
}else{
|
||||||
$("#fabtn_go_to_comment").addClass("d-none");
|
$("#fabtn_go_to_comment").addClass("d-none");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理滚动位置
|
||||||
if ($("html").hasClass("banner-as-cover")){
|
if ($("html").hasClass("banner-as-cover")){
|
||||||
if (!$("#main").hasClass("article-list-home")){
|
if (!$("#main").hasClass("article-list-home")){
|
||||||
pjaxScrollTop = 0;
|
pjaxScrollTop = 0;
|
||||||
@@ -2649,40 +2759,17 @@ $(document).pjax("a[href]:not([no-pjax]):not(.no-pjax):not([target='_blank']):no
|
|||||||
|
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
}).on('pjax:end', function() {
|
}).on('pjax:end', function() {
|
||||||
// 再次确保资源正确加载
|
|
||||||
setTimeout(function() {
|
|
||||||
waterflowInit();
|
|
||||||
lazyloadInit();
|
|
||||||
|
|
||||||
// 重置移动端目录状态
|
// 重置移动端目录状态
|
||||||
if (typeof window.resetMobileCatalog === 'function') {
|
if (typeof window.resetMobileCatalog === 'function') {
|
||||||
|
try {
|
||||||
window.resetMobileCatalog();
|
window.resetMobileCatalog();
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('resetMobileCatalog failed:', err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// GT4: PJAX 后确保评论页验证码已初始化
|
// GT4: PJAX 后确保评论页验证码已初始化
|
||||||
try {
|
resetGT4Captcha();
|
||||||
if ($('#geetest-captcha').length > 0) {
|
|
||||||
// 重置前端状态,避免重复提交阻塞
|
|
||||||
window.geetestVerified = false;
|
|
||||||
window.geetestAutoSubmitting = false;
|
|
||||||
// 清空隐藏字段,防止残留导致 pass_token 复用
|
|
||||||
$('#geetest_lot_number').val('');
|
|
||||||
$('#geetest_captcha_output').val('');
|
|
||||||
$('#geetest_pass_token').val('');
|
|
||||||
$('#geetest_gen_time').val('');
|
|
||||||
// 清空容器,防止重复 appendTo 导致多个实例
|
|
||||||
$('#geetest-captcha').empty();
|
|
||||||
// 若页面脚本已提供初始化方法,则调用以加载验证码
|
|
||||||
if (typeof initGeetestCaptcha === 'function') {
|
|
||||||
initGeetestCaptcha();
|
|
||||||
} else if (typeof loadGeetestScript === 'function' && typeof initGeetestCaptchaCore === 'function') {
|
|
||||||
loadGeetestScript(function(){ initGeetestCaptchaCore(); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('Geetest init on PJAX failed:', e);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/*Reference 跳转*/
|
/*Reference 跳转*/
|
||||||
|
|||||||
Reference in New Issue
Block a user