如何用按钮切换Highlight.js代码高亮明暗主题?求更优实现方案
优化highlight.js主题切换的几种高效方案
你的实现已经能正常运行,但存在一个小bug:if分支未添加花括号,导致currentTheme = "dark"语句会无条件执行,先把这个问题修复后,再给你几个更高效、可维护的实现思路:
1. 用配置对象统一管理主题
把主题URL集中存放在配置对象中,避免硬编码,后续新增主题时只需修改配置,扩展性更强:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>highlight.js</title> <link rel="stylesheet" id="theme-link" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/go.min.js"></script> <script> hljs.highlightAll(); // 统一管理主题信息 const themes = { light: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css", dark: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/tomorrow-night-blue.css" }; let currentTheme = "light"; function toggleTheme() { const themeLink = document.getElementById("theme-link"); currentTheme = currentTheme === "light" ? "dark" : "light"; themeLink.href = themes[currentTheme]; } </script> </head> <body> <pre><code class="language-python">print("Hello World!");</code></pre> <pre><code class="language-python">print("Hello World!");</code></pre> <button onclick="toggleTheme()">Toggle theme</button> </body> </html>
2. 用localStorage记住用户选择
将用户最后一次选择的主题存入本地存储,下次打开页面时自动加载,提升用户体验:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>highlight.js</title> <link rel="stylesheet" id="theme-link" href=""> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/go.min.js"></script> <script> hljs.highlightAll(); const themes = { light: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css", dark: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/tomorrow-night-blue.css" }; const themeLink = document.getElementById("theme-link"); // 优先级:本地存储 > 默认浅色主题 let currentTheme = localStorage.getItem("hljs-theme") || "light"; // 初始化主题 themeLink.href = themes[currentTheme]; function toggleTheme() { currentTheme = currentTheme === "light" ? "dark" : "light"; themeLink.href = themes[currentTheme]; localStorage.setItem("hljs-theme", currentTheme); } </script> </head> <body> <pre><code class="language-python">print("Hello World!");</code></pre> <pre><code class="language-python">print("Hello World!");</code></pre> <button onclick="toggleTheme()">Toggle theme</button> </body> </html>
3. 预加载主题CSS,消除切换延迟
提前加载所有主题的CSS文件,通过禁用/启用样式表实现切换,避免每次切换时的网络请求延迟:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>highlight.js</title> <!-- 预加载两个主题,默认禁用深色主题 --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/tomorrow-night-blue.css" id="dark-theme" disabled> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/go.min.js"></script> <script> hljs.highlightAll(); const lightTheme = document.querySelector('link[href*="default.min.css"]'); const darkTheme = document.getElementById("dark-theme"); let isDark = false; function toggleTheme() { isDark = !isDark; lightTheme.disabled = isDark; darkTheme.disabled = !isDark; } </script> </head> <body> <pre><code class="language-python">print("Hello World!");</code></pre> <pre><code class="language-python">print("Hello World!");</code></pre> <button onclick="toggleTheme()">Toggle theme</button> </body> </html>
4. 结合系统明暗偏好自动适配
通过window.matchMedia检测系统的明暗模式偏好,自动设置初始主题,同时保留手动切换的能力:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>highlight.js</title> <link rel="stylesheet" id="theme-link" href=""> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/go.min.js"></script> <script> hljs.highlightAll(); const themes = { light: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css", dark: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/tomorrow-night-blue.css" }; const themeLink = document.getElementById("theme-link"); let currentTheme; // 检测系统明暗偏好 const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; // 优先级:本地存储 > 系统偏好 > 默认浅色 currentTheme = localStorage.getItem("hljs-theme") || (prefersDark ? "dark" : "light"); themeLink.href = themes[currentTheme]; function toggleTheme() { currentTheme = currentTheme === "light" ? "dark" : "light"; themeLink.href = themes[currentTheme]; localStorage.setItem("hljs-theme", currentTheme); } // 可选:监听系统偏好变化,未手动设置时自动跟随 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { if (!localStorage.getItem("hljs-theme")) { currentTheme = e.matches ? "dark" : "light"; themeLink.href = themes[currentTheme]; } }); </script> </head> <body> <pre><code class="language-python">print("Hello World!");</code></pre> <pre><code class="language-python">print("Hello World!");</code></pre> <button onclick="toggleTheme()">Toggle theme</button> </body> </html>
额外小提示
- 原代码中
<pre>和<code>标签内的多余缩进会导致代码显示时带不必要的空格,建议将代码紧贴标签书写,如上述示例所示。 - 如果需要支持更多主题,只需在
themes配置对象中新增键值对即可,无需修改切换逻辑。
内容的提问来源于stack exchange,提问作者codebysumit
相关产品推荐
相关产品推荐

