JS中getElementById在if语句失效,暗黑模式按钮无法持久隐藏
解决暗黑模式持久化后按钮状态不保存及DOM读取报错问题
碰到的Uncaught TypeError: Cannot read properties of null (reading 'style')是核心问题——你的JS代码在页面DOM元素加载完成前就执行了。当代码跑到document.getElementById('dark').style.display这行时,页面上的<a id='dark'>还没被浏览器解析出来,所以返回null,自然没法读取style属性。这就是为什么刷新后按钮状态不恢复,但body的样式能生效(因为body是页面最先加载的元素,大概率已经存在)。
方案1:确保DOM加载完成后执行初始化代码
把主题初始化代码放在DOMContentLoaded事件回调里,只有当页面所有DOM元素都加载完成后,才会执行读取按钮元素的操作:
修改后的JS代码:
// 缓存元素,避免重复查询DOM const body = document.querySelector("body"); let darkBtn, lightBtn; function dark() { body.style.color = 'white'; body.style.backgroundColor = 'black'; darkBtn.style.display = 'none'; lightBtn.style.display = 'block'; localStorage.setItem('darkmode', 'true'); // localStorage只能存字符串,统一存字符串避免类型问题 } function light() { body.style.color = 'black'; body.style.backgroundColor = 'white'; lightBtn.style.display = 'none'; darkBtn.style.display = 'block'; localStorage.setItem('darkmode', 'false'); } // 等待DOM加载完成后再获取按钮并初始化主题 document.addEventListener('DOMContentLoaded', () => { darkBtn = document.getElementById('dark'); lightBtn = document.getElementById('light'); const theme = localStorage.getItem('darkmode'); if (theme === "true") { body.style.color = 'white'; body.style.backgroundColor = 'black'; darkBtn.style.display = 'none'; lightBtn.style.display = 'block'; } else if (theme === "false") { body.style.color = 'black'; body.style.backgroundColor = 'white'; lightBtn.style.display = 'none'; darkBtn.style.display = 'block'; } });
方案2:把JS脚本放在HTML底部(更简单)
如果不想用事件监听,也可以把<script>标签放在</body>标签上方,浏览器会先解析完所有HTML元素,再执行JS代码:
<a id='dark' class='navbar-link' href="#" onclick="dark()" role="button">Darkmode!</a> <a id='light' class='navbar-link' href="#" onclick="light()" role="button">Lightmode!</a> <!-- 把脚本放在body结束前 --> <script> var body = document.querySelector("body"); // 提前缓存按钮元素,避免重复查询 var darkBtn = document.getElementById('dark'); var lightBtn = document.getElementById('light'); var theme = localStorage.getItem('darkmode'); function dark() { body.style.color = 'white'; body.style.backgroundColor = 'black'; darkBtn.style.display = 'none'; lightBtn.style.display = 'block'; localStorage.setItem('darkmode', 'true'); } function light() { body.style.color = 'black'; body.style.backgroundColor = 'white' lightBtn.style.display = 'none'; darkBtn.style.display = 'block'; localStorage.setItem('darkmode', 'false'); } if (theme == "true") { body.style.color = 'white'; body.style.backgroundColor = 'black'; darkBtn.style.display = 'none'; lightBtn.style.display = 'block'; } else if (theme == "false") { body.style.color = 'black'; body.style.backgroundColor = 'white' lightBtn.style.display = 'none'; darkBtn.style.display = 'block'; } </script> </body>
额外优化建议(可选)
用CSS类控制主题和按钮显示,比直接操作style属性更易维护:
- 先写CSS:
body.dark-theme { color: white; background-color: black; } body.light-theme { color: black; background-color: white; } .hidden { display: none; }
- 修改JS代码:
const body = document.querySelector("body"); const darkBtn = document.getElementById('dark'); const lightBtn = document.getElementById('light'); function setDarkTheme() { body.classList.add('dark-theme'); body.classList.remove('light-theme'); darkBtn.classList.add('hidden'); lightBtn.classList.remove('hidden'); localStorage.setItem('darkmode', 'true'); } function setLightTheme() { body.classList.add('light-theme'); body.classList.remove('dark-theme'); lightBtn.classList.add('hidden'); darkBtn.classList.remove('hidden'); localStorage.setItem('darkmode', 'false'); } document.addEventListener('DOMContentLoaded', () => { const theme = localStorage.getItem('darkmode'); theme === 'true' ? setDarkTheme() : setLightTheme(); });
内容的提问来源于stack exchange,提问作者Feff
相关产品推荐
相关产品推荐

