如何用javascript实现路由_前端路由的原理是什么【教程】

11次阅读

前端路由需依赖history.pushState和popstate/hashchange事件实现无刷新导航,避免仅监听click导致前进/后退失效、刷新404及seo问题;必须与浏览器历史联动并处理首次加载、重复绑定等细节。

如何用javascript实现路由_前端路由的原理是什么【教程】

前端路由不需要服务端参与就能切换页面视图,核心靠的是 history.pushStatehashchange 事件 —— 但直接手写一个“可用”的路由远比想象中容易出错。

为什么不能只监听 click 事件跳转?

单纯给所有 a 标签加 prEventDefault() 再手动更新 dom,会丢失浏览器原生能力:前进/后退按钮失效、刷新页面 404、SEO 友好性归零。真正的前端路由必须和浏览器历史栈联动。

  • history.pushState() 不触发页面刷新,但会把新状态推入历史栈,同时改变地址栏 URL(注意:不会发送 http 请求)
  • popstate 事件在用户点击前进/后退按钮时触发,是响应式更新视图的唯一可靠时机
  • hashchange 更轻量,兼容性更好(IE8+),但 URL 中带 #,对 SEO 和部分后端代理不友好

history.pushState 的三个参数到底怎么填?

调用格式是 history.pushState(state, title, url),其中:

  • state 是任意可序列化的 js 值(如 {page: 'user', id: 123}),它会被存入历史记录,后续在 popstate 事件中通过 event.state 取回 —— 这是传递路由参数最干净的方式,别硬塞到 URL 查询字符串
  • title 目前所有主流浏览器都忽略它,传空字符串 '' 即可
  • url 必须是同源的相对路径(如 /user/123),不能跨域,也不能是完整 URL(如 https://xxx.com/user),否则报错 SecurityError

如何避免 popstate 事件重复触发或漏触发?

常见陷阱是:在单页应用中,popstate 可能被多次绑定(比如组件反复挂载)、也可能在首次加载时没触发(因为初始页面不是由 pushState 进来的)。

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

  • 务必使用 addEventListener('popstate', handler, { passive: true }),且只绑定一次(例如在应用初始化时)
  • 首次加载需主动匹配当前 URL 并渲染对应视图,不能等 popstate —— 它只响应“导航动作”,不响应“初始加载”
  • 如果用了 replaceState(比如登录后替换掉 /login 路径),它不会触发 popstate,所以状态同步逻辑要独立处理
const router = {   routes: new Map(),   init() {     // 首次加载:解析当前 location.pathname     this.render(location.pathname);     // 绑定 popstate     addEventListener('popstate', (e) => {       this.render(e.state?.path || location.pathname);     });   },   go(path) {     history.pushState({ path }, '', path);     this.render(path);   },   render(path) {     const Component = this.routes.get(path) || NotFound;     document.getElementById('app').innerhtml = Component();   } };

Hash 模式下 location.hash 的值带不带 #

带。读取时 location.hash 返回的是完整字符串,如 #/user/123;但 pushState 不适用 hash 模式,你得用 location.hash = '/user/123'(注意这里不用写 #,浏览器会自动补上)。

  • 监听变化要用 addEventListener('hashchange', ...),它的触发时机和 popstate 类似,但更早兼容
  • hashchange 回调里,event.oldURLevent.newURL 是完整 URL 字符串,解析推荐用 location.hash.slice(1)
  • 不要混用 hash 和 history 模式:比如在 history 模式下手动改 location.hash,会导致 URL 变成 /user#abc,既难维护又破坏语义

真正难的不是实现跳转,而是让路由状态和组件生命周期、数据请求、滚动位置、嵌套路由、动态加载全部对齐 —— 手写路由很快会变成状态泥潭。除非你明确知道哪些功能可以砍掉,否则建议直接用 react-routervue-router 的最小运行时版本。

text=ZqhQzanResources