传统的多页面应用,路由及相关的状态都是由后端控制的,发生变化时也由后端来做相应的处理。
前端路由是指在单页应用(Single Page Application,SPA)中,根据用户的 URL 变化来动态切换不同的视图,而不需要重新加载整个页面。这使得用户体验更加流畅。前端路由的核心是通过监听浏览器 URL 的变化,来决定应该渲染哪个组件或视图。
History 模式
利用 HTML5 History API (pushState 和 replaceState 方法) 来操作浏览器的历史记录,实现 URL 的变化。优点是 URL 更加美观,缺点是在不支持 HTML5 的浏览器中需要回退到 Hash 模式。
Histoyr API:
- back,返回前一页。
- forward,在浏览器记录中前往下一页。
- go,在当前页面的相对位置从浏览器历史记录加载页面。
- pushState,按指定的名称和 URL 将数据 push 进会话历史栈。
- replaceState,指定的数据、名称和 URL,更新历史栈上最新的入口。
Hash 模式
通过监听 URL 中的 # 后面的内容来实现路由切换。location.hash 获取#后面的内容,当一个窗口的 Hash(URL 中#后面的部分)改变时就会触发 hashchange 事件。监听相应的事件:window.addEventListener("hashchange", funcRef, false)。绑定路由与函数的映射关系,就可以完成一个基础的路由系统。优点是兼容性好,缺点是 URL 不够美观。
实现一个路由系统
<!DOCTYPE html>
<html>
<head>
<title>Simple Router</title>
<script>
class Router {
constructor(routes) {
this.routes = routes;
this.init();
}
init() {
window.addEventListener('hashchange', this.handleRouteChange.bind(this));
window.addEventListener('load', this.handleRouteChange.bind(this));
}
handleRouteChange() {
const hash = window.location.hash.slice(1) || '/';
const route = this.routes.find(r => r.path === hash);
if (route) {
const view = new route.component();
document.getElementById('app').innerHTML = view.render();
}
}
}
class Home {
render() {
return `<h1>Home</h1>`;
}
}
class About {
render() {
return `<h1>About</h1>`;
}
}
class Contact {
render() {
return `<h1>Contact</h1>`;
}
}
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/contact', component: Contact }
];
new Router(routes);
</script>
</head>
<body>
<nav>
<a href="#/">Home</a>
<a href="#/about">About</a>
<a href="#/contact">Contact</a>
</nav>
<div id="app"></div>
</body>
</html>