前言
单页应用刷新,速度很快,不刷新,比预加载还快
正文
问题是原来的功能都没有考虑这一点,缝缝补补一下午了,也就把灯箱、锚点目录,跳转页加上去了,还有很多js功能都没有,回退了,不过还是把代码放这记录一下
themes\hugo-magic\layouts\_default\baseof.html
下面的是完整代码
<!DOCTYPE html>
<html lang="{{ .Site.LanguageCode }}" dir="{{ default `ltr` .Language.LanguageDirection }}">
<head>
<!-- 立即执行主题初始化,必须放在最前面 -->
<script>
(function() {
// 防止重复初始化和闪烁
if (document.documentElement.dataset.scheme) return;
const colorSchemeKey = 'StackColorScheme';
const colorScheme = localStorage.getItem(colorSchemeKey) || 'dark';
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
// 立即设置主题,防止闪烁
document.documentElement.dataset.scheme =
colorScheme === 'dark' || (colorScheme === 'auto' && prefersDark)
? 'dark'
: 'light';
})();
</script>
<style>
/* 预设主题样式,防止闪烁 */
:root[data-scheme="light"] {
--theme-bg: #ffffff;
--theme-text: #000000;
background-color: #ffffff;
color: #000000;
}
:root[data-scheme="dark"] {
--theme-bg: #1a1a1a;
--theme-text: #ffffff;
background-color: #1a1a1a;
color: #ffffff;
}
/* 添加渐变效果,但仅在初始加载后 */
.theme-loaded {
transition: background-color 0.3s ease, color 0.3s ease;
}
/* 添加页面切换动画 */
.turbolinks-progress-bar {
height: 3px;
background-color: var(--theme-text);
}
</style>
<!-- 添加Turbolinks支持 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/turbolinks/5.2.0/turbolinks.js"></script>
<script>
// 配置Turbolinks
window.Turbolinks = Turbolinks;
// 定义外部链接处理函数
function handleExternalLinks() {
function checkParent(element, classNames) {
while (element) {
if (element.classList && classNames.some(cn => element.classList.contains(cn))) {
return true;
}
element = element.parentElement;
}
return false;
}
// 需要排除的类名
var excludedClasses = ['talks_comments', 'tiaozhuan-button', 'search-result'];
// 需要排除的页面路径
var excludedPaths = ['/search/', '/search'];
document.body.addEventListener('click', function(e) {
// 如果当前页面是搜索页面,不处理链接
if (excludedPaths.some(path => window.location.pathname.startsWith(path))) {
return;
}
let target = e.target;
while (target && target.nodeName !== 'A') {
target = target.parentNode;
}
if (target && target.nodeName === 'A' &&
!checkParent(target, excludedClasses) &&
target.hostname !== window.location.hostname) {
e.preventDefault();
let encodedUrl = btoa(target.href);
let url = '/tiaozhuan?target=' + encodedUrl;
window.open(url, '_blank');
}
});
}
// 在页面加载和Turbolinks加载时都初始化外部链接处理
document.addEventListener('DOMContentLoaded', handleExternalLinks);
document.addEventListener('turbolinks:load', handleExternalLinks);
// 处理目录锚点点击
function handleTocClick(e) {
const link = e.target.closest('a');
if (!link) return;
const href = link.getAttribute('href');
if (!href || !href.startsWith('#')) return;
e.preventDefault();
const targetId = href.slice(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
e.preventDefault();
// 平滑滚动到目标位置
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
// 更新 URL,但不触发滚动
history.pushState(null, null, href);
}
}
// 在页面加载和Turbolinks加载时绑定目录点击事件
function initTocClickHandler() {
const toc = document.querySelector('#TableOfContents');
if (toc) {
toc.removeEventListener('click', handleTocClick);
toc.addEventListener('click', handleTocClick);
}
}
document.addEventListener('DOMContentLoaded', initTocClickHandler);
document.addEventListener('turbolinks:load', initTocClickHandler);
// 处理 Turbolinks 页面加载后的锚点跳转
document.addEventListener('turbolinks:load', function() {
const hash = window.location.hash;
if (hash) {
const targetElement = document.querySelector(hash);
if (targetElement) {
setTimeout(() => {
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}, 100);
}
}
});
// 处理Turbolinks的外部链接
document.addEventListener('turbolinks:before-visit', function(event) {
const url = new URL(event.data.url);
const isExternal = url.hostname !== window.location.hostname;
if (isExternal) {
event.preventDefault();
}
});
// 加载目录滚动监听脚本
function loadScrollspy() {
return new Promise((resolve, reject) => {
if (window.setupScrollspy) {
resolve(window.setupScrollspy);
return;
}
const script = document.createElement('script');
script.src = '/ts/scrollspy.js';
script.onload = () => resolve(window.setupScrollspy);
script.onerror = reject;
document.head.appendChild(script);
});
}
// 初始化目录滚动监听
async function initScrollspy() {
try {
const setupScrollspy = await loadScrollspy();
setupScrollspy();
} catch (error) {
console.error('Failed to initialize scrollspy:', error);
}
}
// 在页面加载和Turbolinks加载时初始化目录滚动监听
document.addEventListener('DOMContentLoaded', initScrollspy);
document.addEventListener('turbolinks:load', initScrollspy);
// 加载Twikoo脚本
function loadTwikoo() {
return new Promise((resolve, reject) => {
if (window.twikoo) {
resolve(window.twikoo);
return;
}
const script = document.createElement('script');
script.src = '//cdn.jsdelivr.net/npm/twikoo@1.6.40/dist/twikoo.all.min.js';
script.onload = () => resolve(window.twikoo);
script.onerror = reject;
document.head.appendChild(script);
});
}
// 初始化Twikoo评论
async function initTwikoo() {
const tcomment = document.getElementById('tcomment');
if (!tcomment) return;
try {
const twikoo = await loadTwikoo();
// 清空评论区内容
tcomment.innerHTML = '';
// 重新初始化Twikoo
await twikoo.init({
envId: '{{ .Site.Params.comments.twikoo.envId }}',
el: '#tcomment'
});
} catch (error) {
console.error('Failed to initialize Twikoo:', error);
}
}
// 在Turbolinks加载完成后初始化Twikoo
document.addEventListener('turbolinks:load', initTwikoo);
</script>
{{- partial "head/colorScheme" . -}}
{{- partial "head/head.html" . -}}
{{- block "head" . -}}{{ end }}
</head>
<body class="{{ block `body-class` . }}{{ end }}">
<script>
// 添加主题加载完成标记,启用过渡效果
document.documentElement.classList.add('theme-loaded');
// 启动Turbolinks
if (typeof Turbolinks !== 'undefined') {
Turbolinks.start();
}
</script>
{{/* The container is wider when there's any activated widget */}}
{{- $hasWidget := false -}}
{{- range .Site.Params.widgets -}}
{{- if gt (len .) 0 -}}
{{- $hasWidget = true -}}
{{- end -}}
{{- end -}}
<div class="container main-container flex on-phone--column {{ if $hasWidget }}extended{{ else }}compact{{ end }}">
{{- block "left-sidebar" . -}}
{{ partial "sidebar/left.html" . }}
{{- end -}}
{{- block "right-sidebar" . -}}{{ end }}
<main class="main full-width">
{{- block "main" . }}{{- end }}
</main>
</div>
{{ partial "footer/include.html" . }}
<!-- 添加 medium-zoom 支持 -->
<script src="https://s4.zstatic.net/npm/medium-zoom/dist/medium-zoom.min.js"></script>
<style>
/* 自定义 medium-zoom 样式 */
.medium-zoom-overlay {
background-color: rgba(0, 0, 0, 0.95) !important;
z-index: 999;
}
.medium-zoom-image--opened {
z-index: 1000;
}
</style>
<script>
// 全局变量存储zoom实例
let zoomInstance = null;
// 初始化图片缩放
function initMediumZoom() {
// 如果已经初始化过,先清理
if (zoomInstance) {
zoomInstance.detach();
}
if (typeof mediumZoom !== 'undefined') {
// 创建新的实例
zoomInstance = mediumZoom('article.main-article img:not(.nozoom):not(.site-logo):not(.link-card .article-image img):not(.article-list--compact.links .article-image img):not(.article-header .article-image img)', {
margin: 24,
background: 'rgba(0, 0, 0, 0.95)',
scrollOffset: 0,
});
}
}
// 初始化
initMediumZoom();
// Turbolinks 页面切换后重新初始化
document.addEventListener('turbolinks:load', initMediumZoom);
</script>
</body>
</html>