HTML5 词条目录
前端Wiki/HTML5/深入/现代 API 与组件

history 路由基础

单页应用(SPA)"页面不刷新、地址栏却变化"靠的是 history API 两个方法:history.pushState(状态, 标题, url) 往浏览记录里压入一条新地址并更新地址栏,页面本身不重载;replaceState() 作用相同但替换当前记录而非新增。配合 popstate 事件——用户点前进/后退时触发——就能搭出最小路由。

最小路由由三部分组成:路由表(路径 → 内容的映射)、拦截链接(给站内 a 的 click 调 preventDefault,改用 pushState 跳转 + 手动渲染)、监听 popstate(前进后退时按 location.pathname 重新渲染)。地址栏、浏览记录、页面内容三者就这样保持同步。

一个必须知道的局限:用户在 /about 上刷新页面或直接访问时,请求会发到服务器,而服务器上并没有这个路径,会 404。所以生产环境需要服务器兜底配置——把所有路径都回退到 index.html(Nginx 的 try_files、各类云平台的 rewrite 规则都是干这个的)。

本节要点pushState/replaceState 改地址栏不刷新页面,popstate 监听前进后退;路由 = 路由表 + 拦截 a 点击 + popstate 渲染;服务器需配置所有路径回退到 index.html。
HTML
<a href="/home" data-link>首页</a>
<a href="/about" data-link>关于</a>
<div id="view"></div>
<script>
  // 路由表:路径 → 页面内容
  var routes = {
    '/home': '欢迎来到首页',
    '/about': '这是关于页面'
  };
  function render(path) {
    document.getElementById('view').textContent = routes[path] || '404 未找到';
  }

  // 拦截站内链接:阻止刷新,改用 pushState 无感切换
  document.querySelectorAll('a[data-link]').forEach(function (a) {
    a.addEventListener('click', function (e) {
      e.preventDefault();
      history.pushState({}, '', a.href);   // 地址栏变化,页面不重载
      render(a.pathname);
    });
  });

  // 前进/后退按钮:按当前路径重新渲染
  window.addEventListener('popstate', function () {
    render(location.pathname);
  });

  render(location.pathname);   // 首次进入也渲染
</script>
🔗 相关词条HTML同步事件组件