diff options
| author | mayx <mayx@outlook.com> | 2026-05-21 10:11:01 +0000 |
|---|---|---|
| committer | mayx <mayx@outlook.com> | 2026-05-21 10:11:01 +0000 |
| commit | d6274791a8f794d11e7e9acc58c3d45abe11a76c (patch) | |
| tree | e416fe6f18460d6ba655b7f99e8db5b045cbd9cb /assets | |
| parent | 111dc1e25f43a1c783192d214a3697dee33bae82 (diff) | |
Update 2 files
- /assets/js/pjax.js
- /index.html
Diffstat (limited to 'assets')
| -rw-r--r-- | assets/js/pjax.js | 65 |
1 files changed, 50 insertions, 15 deletions
diff --git a/assets/js/pjax.js b/assets/js/pjax.js index 3664392..e81b974 100644 --- a/assets/js/pjax.js +++ b/assets/js/pjax.js @@ -17,6 +17,7 @@ // ========== 工具函数 ========== var _loadedScripts = {}; + var _pendingScripts = []; /** 动态加载外部 CSS(避免重复加载) */ function loadCSS(href) { @@ -24,7 +25,11 @@ $('<link rel="stylesheet" href="' + href + '" />').appendTo('head'); } - /** 动态加载外部 JS(去重) */ + /** + * 动态加载外部 JS(避免重复) + * 用对象跟踪已加载的 URL,而不是检查 DOM 中的 <script> 标签 + * (pjax 替换容器内容后,惰性 <script> 标签存在但不代表已执行) + */ function loadScript(src, callback) { if (_loadedScripts[src]) { if (typeof callback === 'function') callback(); @@ -37,6 +42,32 @@ document.body.appendChild(s); } + /** + * 按顺序执行脚本数组(内联和外部混合) + * 外部脚本加载完成后再执行后续内联脚本,保持依赖顺序 + */ + function executeScripts(scripts) { + var idx = 0; + function runNext() { + while (idx < scripts.length) { + var s = scripts[idx]; + idx++; + if (s.src) { + loadScript(s.src, runNext); + return; // 等待 onload 回调 + } + try { + (window.execScript || function (code) { + window['eval'].call(window, code); + })(s.text); + } catch (e) { + console.warn('[pjax] inline script exec error:', e); + } + } + } + runNext(); + } + // ========== 页面类型判断 ========== /** 是否为文章页(非首页/分页) */ @@ -98,7 +129,7 @@ } } - /** AI 摘要(post.html 内联脚本,pjax 后触发) */ + /** AI 摘要(post.html 内联脚本,pjax 后由 executeScripts 触发) */ function reinitAISummary() { if (typeof ai_gen === 'function' && $('#ai-output').length) { try { ai_gen(); } catch (e) { /* ignore */ } @@ -231,16 +262,17 @@ $('body').removeClass('pjax-loading'); // 清理可能残留的浮层(如推荐文章 tooltip,hover 后点击跳转时 mouseleave 来不及触发) $('.content-tooltip').hide(); + // go() 路径:脚本在 DOM 替换前提取到了 _pendingScripts,需在此执行 + // pjax 库路径:_pendingScripts 为空,pjax 库自行处理了脚本执行 + if (_pendingScripts.length > 0) { + executeScripts(_pendingScripts); + _pendingScripts = []; + } onPjaxComplete(); } /** 暴露给模板内 onclick/onchange 调用的导航函数 */ window.go = function (url) { - if (!url || url === '#') return; - if (/^(https?:)?\/\//.test(url) || url.startsWith('mailto:')) { - window.location.href = url; - return; - } $('body').addClass('pjax-loading'); $.ajax({ url: url, @@ -253,13 +285,16 @@ var doc = (new DOMParser()).parseFromString(html, 'text/html'); var fragment = doc.querySelector(CONTAINER); if (fragment) { - // 用 adoptNode 搬运所有子节点(包括 script 元素),让浏览器自行处理脚本执行 - // 这能正确支持 type="module"、顶层 await 等,避免手动提取重建的坑 - $(CONTAINER).empty(); // jQuery 清理旧元素的事件和数据,避免内存泄漏 - var container = document.querySelector(CONTAINER); - while (fragment.firstChild) { - container.appendChild(document.adoptNode(fragment.firstChild)); - } + // 先提取脚本(jQuery html() 会移除并可能异步处理脚本) + _pendingScripts = []; + fragment.querySelectorAll('script').forEach(function (s) { + _pendingScripts.push({ + src: s.src || null, + text: s.textContent + }); + s.remove(); + }); + $(CONTAINER).html(fragment.innerHTML); document.title = doc.title; history.pushState({ url: url }, document.title, url); doPjaxComplete(); @@ -313,4 +348,4 @@ reinitCopyButtons(); }); -})(jQuery); +})(jQuery);
\ No newline at end of file |
