JavaScript如何实现路由_前端路由原理是什么

14次阅读

前端路由本质是URL状态管理,通过history.pushState()等API修改地址栏并监听popstate事件实现无刷新导航,将路径映射到组件渲染,分Hash与History两种模式。

JavaScript如何实现路由_前端路由原理是什么

前端路由本质是 URL 状态管理,不是真正跳转

前端路由不触发页面刷新,也不向服务端发请求。它靠的是浏览器提供的 history.pushState()history.replaceState() 修改地址栏,配合 popstate 事件监听返回/前进动作。所谓“路由”,其实是把 URL 路径映射到组件或视图的逻辑,由 js 主动控制 dom 渲染内容。

两种实现方式:Hash 模式与 History 模式

Hash 模式依赖 URL 中 # 后的部分(location.hash),无需服务端配合;History 模式用 history.pushState() 改变完整路径(如 /user/123),但要求服务端对所有前端路由路径都返回同一份 html(否则 404)。

  • Hash 模式兼容性更好,IE8+ 都支持,URL 会带 #,例如 https://example.com/#/about
  • History 模式更美观,但开发时需配 webpack-dev-server 的 historyApiFallback: true,上线时 nginx 需配置 try_files $uri $uri/ /index.html;
  • 不能直接用 location.href = '/xxx' 切换 History 路由——这会强制刷新;必须用 history.pushState()封装好的方法

手写一个最小可用的 History 路由

核心就三件事:监听变化、匹配路径、渲染对应内容。不需要框架也能跑起来:

const routes = {   '/': () => document.getElementById('app').innerHTML = '首页',   '/about': () => document.getElementById('app').innerHTML = '关于页',   '/user/:id': (params) => document.getElementById('app').innerHTML = `用户 ${params.id}` };  function route() {   const path = location.pathname;   for (const [routePath, handler] of Object.entries(routes)) {     if (routePath === path) {       handler();       return;     }     // 简单支持带参数的路径(实际应使用正则)     if (routePath.startsWith('/user/') && path.startsWith('/user/')) {       const id = path.split('/user/')[1];       handler({ id });       return;     }   }   document.getElementById('app').innerHTML = '404'; }  // 初始化 route();  // 监听浏览器前进/后退 window.addEventListener('popstate', route);  // 导航函数(代替 a 标签默认行为) function navigate(to) {   history.pushState({}, '', to);   route(); }

注意:popstate 不会在 pushStatereplaceState 时触发,只响应用户点击前进/后退按钮,或调用 history.back() 等操作。

立即学习Java免费学习笔记(深入)”;

为什么 pushState 后要手动调用 route()?

history.pushState() 只改 URL 和历史,不会自动触发任何回调。你得自己执行匹配和渲染逻辑。很多初学者卡在这儿:点了导航没反应,是因为只写了 pushState,忘了同步更新视图。

  • react routervue Router 都是在内部封装了这一流程:拦截导航 → 更新 URL → 匹配 → 渲染
  • 如果用原生事件绑定,记得给 onclick="navigate('/xxx'); return false;",否则仍是整页跳转
  • 服务端永远不知道前端路由的存在——它只看到首次请求的 GET /,后续所有 /user/123 都是前端自己消化的

真正的难点不在怎么写路由,而在如何让路由状态与组件状态、数据加载、滚动位置、seo 等协同工作。这些才是框架存在的理由。

text=ZqhQzanResources