面试题库 词条目录
前端Wiki/面试题库/框架与工程化/工程化与软技能

前端路由原理(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 需服务端兜底;手写路由 = 监听 + 匹配 + 渲染。
🔗 相关词条前端工程化VueNode.js