前端路由原理(hash / history)
前端路由让 SPA 在不刷新页面的情况下切换视图。两种模式:hash 路由(URL 带 #,变化触发 hashchange 事件,兼容好但不美观);history 路由(pushState / replaceState 改 URL、popstate 监听前进后退,需要服务端配合:所有路径都返回 index.html,否则刷新 404)。Vue Router 与 React Router 都默认 history,可切 hash。
手写路由核心:监听 URL 变化 → 匹配路由表 → 渲染对应组件。加分点:提到 history.pushState 不会触发 popstate,需要自己 dispatch 或者改写 pushState;提到嵌套路由与动态参数(/user/:id)用 path-to-regexp 匹配。
- hash:#变化触发 hashchange,无需服务端配合;缺点是丑、SEO 不友好
- history:pushState + popstate,URL 干净,但刷新需服务端 fallback 到 index.html
- 手写路由三步:监听变化 → 路由表匹配 → 渲染视图
JS
// 手写 mini 前端路由(history 模式) const routes = { "/": () => "首页", "/about": () => "关于", "/user/:id": (params) => "用户 " + params.id, }; function matchRoute(path) { // 动态参数匹配 /user/:id for (const rule in routes) { const pattern = rule.replace(/:([^/]+)/g, "([^/]+)"); const m = path.match(new RegExp("^" + pattern + "$")); if (m) { const keys = [...rule.matchAll(/:([^/]+)/g)].map((x) => x[1]); const params = Object.fromEntries(keys.map((k, i) => [k, m[i + 1]])); return routes[rule](params); } } return "404"; } function render() { const path = location.pathname; document.getElementById("app").textContent = matchRoute(path); } // 监听前进 / 后退 window.addEventListener("popstate", render); // 拦截 a 标签点击,走 pushState 不刷新 document.addEventListener("click", (e) => { const a = e.target.closest("a"); if (a && a.target === "_self") { e.preventDefault(); history.pushState({}, "", a.href); render(); } }); render(); console.log("当前路由:", location.pathname, "→", matchRoute(location.pathname));
本节要点hash 走 hashchange 零配置,history 走 pushState + popstate 需服务端兜底;手写路由 = 监听 + 匹配 + 渲染。




