hash变化不触发页面刷新但能被监听,需用hashchange事件响应,并手动执行一次处理函数以初始化状态;通过location.hash.slice(1)解析路径,结合dom显隐实现模块切换。

hash 变化不会触发页面刷新,但能被 JavaScript 监听
直接读写 window.location.hash 不会重载页面,适合做单页内功能切换。编辑器的「预览」「源码」「设置」等模块可以映射到不同 hash 值,比如 #preview、#source、#settings。关键在于:浏览器在地址栏输入新 hash 或点击带 href="#xxx" 的链接时,会自动更新 location.hash 并触发 hashchange 事件——这是实现路由响应的基础。
注意:初始加载时(页面刚打开),hashchange 不会触发,必须手动检查一次 location.hash 来激活对应模块。
监听 hashchange 并切换 UI 模块的最小可行代码
别用框架封装,先跑通逻辑。核心是绑定事件 + 解析 hash + 显示/隐藏对应区域:
function handleHashChange() {
const hash = window.location.hash.slice(1) || 'editor'; // 去掉 #,空值默认 editor
// 隐藏所有模块
document.querySelectorAll('.module').forEach(el => el.classList.add('hidden'));
// 显示目标模块
const targetEl = document.getElementById(hash);
if (targetEl) targetEl.classList.remove('hidden');
}
// 页面加载后立即执行一次
handleHashChange();
// 监听后续变化
window.addEventListener('hashchange', handleHashChange);
常见错误:hashchange 回调里没处理初始状态,导致首次打开 index.html#source 时仍显示默认模块;或者忘了用 slice(1) 去掉 #,导致 getElementById('#source') 查不到元素。
如何让导航链接和键盘操作都生效
纯 hash 路由依赖 HTML 锚点行为,所以导航栏要写成标准链接:
<a href="#editor">编辑</a> <a href="#preview">预览</a> <a href="#source">源码</a>
这样既支持鼠标点击,也支持键盘 Tab 切换 + Enter 触发。但要注意两点:
- 每个模块容器必须有对应
id,且不能含特殊字符(如id="code-editor"是合法的,但id="code/editor"会导致getElementById失败) - 如果编辑器内容区本身可滚动,跳转到
#source后浏览器会尝试滚动到该元素位置,可能干扰编辑体验——可在 CSS 中加scroll-margin-top: 60px;微调,或用event.preventDefault()拦截默认锚点滚动(需自行控制 focus 和 scroll)
hash 路由与编辑器状态耦合时的坑
当用户在「源码」模式下修改了内容,切到「预览」再切回「源码」,得保持光标位置、滚动偏移、未保存标记等状态。hash 本身不存状态,只是个信号,真正要做的:
- 把模块切换逻辑和编辑器实例解耦:例如
editor.switchMode('source')封装好内部状态保存/恢复 - 避免在
hashchange回调里直接操作 DOM 渲染编辑器(如重新初始化 CodeMirror),应复用已有实例并仅切换视图层 - 如果支持浏览器前进/后退,注意
history.pushState和replaceState对 hash 的影响——它们不会触发hashchange,但会改变地址栏。稳妥做法是统一用location.hash = 'xxx'触发变更
hash 最大长度受限(通常 2048 字符),别往里面塞 base64 内容或长配置;需要持久化参数时,应改用 URL search 参数或 localStorage 配合 hash 使用。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











