Vue Router 的 history 模式
注:原文标题写为"Vuex",实际内容为 Vue Router 的 history 模式,特此说明。
Vue Router 的 history 模式充分利用了 history.pushState API 来完成 URL 跳转而不需要重新加载页面。
1. 两种 history 模式
Hash 模式(createWebHashHistory())
import { createRouter, createWebHashHistory } from 'vue-router';
const router = createRouter({
history: createWebHashHistory(),
routes: [/* ... */]
});
在内部传递的 URL 之前使用哈希字符(#)。这部分 URL 从未被发送到服务器,所以不需要在服务器层面进行特殊处理。但对 SEO 不友好。
HTML5 模式(createWebHistory())
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(),
routes: [/* ... */]
});
URL 看起来"正常",如 https://example.com/user/id。但如果没有适当的服务器配置,用户直接访问 https://example.com/user/id 会得到 404。
解决办法:在服务器上添加一个简单的回退路由——URL 不匹配任何静态资源时,返回 index.html。
注意:开启 history 模式后服务器对所有路径都返回
index.html,会"吞掉" 404。要在 Vue 应用里覆盖所有路由并显式提供 404 组件:
const router = new VueRouter({
mode: 'history',
routes: [{ path: '*', component: NotFoundComponent }]
});
如果用 Node.js 后台,可通过服务端路由匹配 URL,未匹配到时返回 404 实现 fallback。
2. 实现原理
实现一个页面操作不会整页刷新、且能在浏览器前进/后退时正确响应的网站:
- 通过
pushState+ajax实现浏览器无刷新前进/后退。 - 一次 ajax 调用成功后,将一条 state 记录加入 history 对象。
- 一条 state 记录包含
url、title、content属性;在popstate事件中可获取。 - 用
content传递数据。 - 通过
window.onpopstate事件监听,响应浏览器前进/后退。
两个问题:
- 打开首页时没有记录:用
replaceState把首页的记录替换掉。 - 页面刷新仍会向服务端请求:把请求的 URL 经后端重定向到一个页面。
3. History API
window.history.back(); // 后退
window.history.go(); // 前进/后退指定步数
window.history.forward(); // 前进
添加 / 修改历史记录条目
HTML5 引入 history.pushState() 和 history.replaceState(),配合 window.onpopstate 使用。
history.pushState(stateObj, 'name', 'path');
window.onpopstate = function (e) { /* ... */ };
history.pushState() 可以改变 referrer:在该 state 后创建的 XMLHttpRequest 对象的 referrer 都会随之改变。
举例
window.onpopstate = function (e) { alert(2); };
const stateObj = { foo: 'bar' };
history.pushState(stateObj, 'page 2', 'bar.html');
地址栏变为 http://mozilla.org/bar.html,但不会加载 bar.html,甚至不会检查它是否存在。
- 用户在 bar.html 点击"后退"按钮 → 触发
alert(2)。 - 用户在 bar.html 跳转到外部页面后又"后退" → 回到
bar.html,history.state含stateObj拷贝,因为页面重新加载了popstate不会触发。 - 再按"后退" → URL 变为
foo.html,触发新的popstate,state 为null。
来源整理自:我的有道云笔记



