手写 Vue Router 中的 Hash 模式和 History 模式
Vue Router
是 Vue.js
的官方路由库,负责管理 Vue
应用中的页面导航。它与 Vue.js
核心深度集成,让用 Vue.js
构建单页应用变得轻而易举。Vue Router
提供两种常见的模式:Hash 模式
和 History 模式
。这两种模式的主要区别在于它们如何管理 URL
,以及如何与浏览器的历史记录 API 交互。
1. URL 路由的基本概念
Vue Router
是 Vue
官方的客户端路由解决方案。
客户端路由的作用是在单页应用 (SPA)
中将浏览器的 URL 和用户看到的内容绑定起来。当用户在应用中浏览不同页面时,URL 会随之更新,但页面不需要从服务器重新加载。
Vue Router
基于 Vue
的组件系统构建,你可以通过配置路由来告诉 Vue Router
为每个 URL
路径显示哪些组件。路由的主要任务包括:
- 根据 URL 切换不同的页面组件。
- 动态管理浏览器的历史记录和导航状态。
Vue Router
使用两种方式来实现路由:
- Hash 模式:利用 URL 中的 # 符号(例如 http://example.com/#/home),基于
hashchange
事件进行路由切换。 - History 模式:利用 HTML5 的 History API(
pushState
、replaceState
)实现路径导航(例如 http://example.com/home),更贴近传统多页面应用的 URL 形式。
2. 实现 Hash 模式的 Vue Router
Hash 模式
是最简单的一种实现方式,它依赖于浏览器原生的 hashchange
事件。下面我们通过手写代码实现一个简化版的 Hash 模式。
2.1 Hash 模式核心代码
class Router {
constructor(routes) {
this.routes = routes; // 路由规则
this.currentPath = ''; // 当前路径
this.init();
}
// 初始化监听
init() {
// 页面加载时触发路由匹配
window.addEventListener('load', this.onHashChange.bind(this));
// 当 hash 改变时,触发路由匹配
window.addEventListener('hashchange', this.onHashChange.bind(this));
}
// 获取当前 hash 路径并匹配路由
onHashChange() {
// 去掉 # 并获取当前的路径
this.currentPath = window.location.hash.slice(1) || '/';
this.matchRoute();
}
// 匹配路径对应的组件并渲染
matchRoute() {
const route = this.routes.find(r => r.path === this.currentPath);
if (route) {
document.getElementById('app').innerHTML = route.component;
} else {
document.getElementById('app').innerHTML = '404 Not Found';
}
}
}
2.2 示例代码
我们可以定义一些简单的路由和组件,并启动这个简化版的 Hash 模式路由。
<div id="app"></div>
<script>
// 定义路由规则
const routes = [
{ path: '/', component: '<h1>Home Page</h1>' },
{ path: '/about', component: '<h1>About Page</h1>' },
{ path: '/contact', component: '<h1>Contact Page</h1>' },
];
// 创建路由实例
const router = new Router(routes);
</script>
当用户访问 /#/about 时,hashchange 事件会触发,路由器会匹配 /about 路径,并在页面上渲染 About Page 组件。
2.3 Hash 模式的优缺点
优点:
- 简单易实现,几乎所有浏览器都支持
hashchange
事件。 - 不需要服务器配置即可使用,因为 hash 不会被发送到服务器。
缺点:
URL
中包含 # 符号,显得不够美观。- 对
SEO
不友好,搜索引擎不会解析 # 后面的内容。
3. 实现 History 模式的 Vue Router
vue-router
默认 hash 模式
—— 使用 URL
的 hash
来模拟一个完整的 URL
,于是当 URL
改变时,页面不会重新加载。该模式基于 HTML5 的 pushState
和 replaceState API
,能够改变浏览器的 URL
而不刷新页面。这种方式让 URL
更加简洁,不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id
就会返回 404,这就不好看了。
3.1 History 模式核心代码
class Router {
constructor(routes) {
this.routes = routes; // 路由规则
this.currentPath = window.location.pathname; // 当前路径
this.init();
}
// 初始化监听
init() {
// 页面加载时触发路由匹配
window.addEventListener('load', this.onPathChange.bind(this));
// 浏览器前进后退时触发路由匹配
window.addEventListener('popstate', this.onPathChange.bind(this));
// 绑定导航点击事件
document.querySelectorAll('a[data-link]').forEach(link => {
link.addEventListener('click', this.onLinkClick.bind(this));
});
}
// 处理路径变化
onPathChange() {
this.currentPath = window.location.pathname;
this.matchRoute();
}
// 匹配路径并渲染组件
matchRoute() {
const route = this.routes.find(r => r.path === this.currentPath);
if (route) {
document.getElementById('app').innerHTML = route.component;
} else {
document.getElementById('app').innerHTML = '404 Not Found';
}
}
// 拦截导航链接点击事件
onLinkClick(event) {
event.preventDefault();
const path = event.target.getAttribute('href');
// 使用 pushState 改变 URL
window.history.pushState({}, '', path);
this.onPathChange();
}
}
3.2 示例代码
为配合 pushState
的使用,我们需要在页面上创建一些导航链接,并通过点击这些链接进行页面切换。
<div id="app"></div>
<nav>
<a href="/" data-link>Home</a>
<a href="/about" data-link>About</a>
<a href="/contact" data-link>Contact</a>
</nav>
<script>
// 定义路由规则
const routes = [
{ path: '/', component: '<h1>Home Page</h1>' },
{ path: '/about', component: '<h1>About Page</h1>' },
{ path: '/contact', component: '<h1>Contact Page</h1>' },
];
// 创建路由实例
const router = new Router(routes);
</script>
在这个示例中,当点击导航链接时,pushState
改变 URL,但不会触发页面刷新,而是通过 Router
手动渲染对应的组件。
3.3 History 模式的优缺点
优点:
URL
更加美观,没有 # 符号。- 更加符合传统的多页面应用,用户体验更好。
- 对
SEO
更友好,搜索引擎可以解析URL
。
缺点:
-需要服务器配合,所有请求必须返回 index.html
,否则会出现 404 错误。
4. 总结
通过手写简化版的 Vue Router
,我们深入理解了 Hash 模式
和 History 模式
的实现原理。Hash 模式依赖于 hashchange
事件,而 History 模式依赖于 pushState
和 replaceState
API。两种模式各有优缺点,可以根据项目需求选择合适的路由模式。
- Hash 模式:简单、无需服务器配置,但
URL
不美观,对SEO
不友好。 - History 模式:
URL
美观且符合SEO
要求,但需要服务器支持。
无论是简单的项目还是大型的单页面应用,Vue Router
都提供了强大的路由管理能力,通过深入了解其原理,我们可以更灵活地运用它来构建现代 Web 应用。