什么是前端路由?
- 前端路由(Frontend Routing)是指在Web应用程序中,通过JavaScript来管理和控制用户在浏览器中访问不同页面的机制。
- 前端路由允许开发人员在单页应用(Single Page Application,SPA)或现代Web应用中创建多个虚拟页面,而
无需每次加载新页面时都向服务器发出请求。 - 前端路由的主要目的是改善用户体验,使Web应用看起来更像传统的多页应用程序,而不是每次页面切换都需要重新加载整个页面。它通过在浏览器的地址栏中监听URL的变化,根据URL的不同加载不同的视图。
Vue Router 不同的历史模式
1. Hash 模式
1.1 vue中使用
hash 模式是用 createWebHashHistory() 创建的:
import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
history: createWebHashHistory(),
routes: [
//...
],
})
它在内部传递的实际 URL 之前使用了一个哈希字符(#)。由于这部分 URL 从未被发送到服务器,所以它不需要在服务器层面上进行任何特殊处理。不过,它在 SEO 中确实有不好的影响。
1.2 原生js实现前端路由
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<a href="#/home">home</a>
<a href="#/about">about</a>
<div class="content">Default</div>
</div>
<script>
const contentEl = document.querySelector('.content')
window.addEventListener('hashchange', (e) => {
console.log(e);
console.log(window.location.hash);
switch (window.location.hash) {
case '#/home':
contentEl.innerHTML = 'Home'
break
case '#/about':
contentEl.innerHTML = 'About'
break
default:
contentEl.innerHTML = 'Default'
}
})
</script>
</body>
</html>
2. History 模式
2.1 vue中使用
History 模式是用 createWebHistory() 创建的:
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [
//...
],
})
- 使用这种历史模式时,URL 会看起来很 "正常".
- 由于我们的应用是一个单页的客户端应用,
如果没有适当的服务器配置,用户在浏览器中直接访问https://example.com/user/id,就会得到一个404错误。 - 要解决这个问题,需要在你的服务器上添加一个简单的回退路由。如果 URL 不匹配任何静态资源,它应提供与你的应用程序中的
index.html相同的页面。
nginx服务器配置
location / {
try_files $uri $uri/ /index.html;
}
2.2 原生js实现前端路由
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<a href="/home">home</a>
<a href="/about">about</a>
<div class="content">Default</div>
</div>
<script>
const changeContent = () => {
switch (location.pathname) {
case "/home":
contentEl.innerHTML = 'Home'
break
case "/about":
contentEl.innerHTML = 'About'
break
default:
contentEl.innerHTML = 'Default'
}
}
const contentEl = document.querySelector('.content')
const aEls = document.getElementsByTagName('a')
console.log(aEls);
for (const aEl of aEls) {
aEl.addEventListener('click', e => {
console.log(e);
e.preventDefault()
const href = aEl.getAttribute('href')
console.log(href);
// history.pushState({}, '', href)
history.replaceState({}, '', href)
changeContent()
})
}
window.addEventListener('popstate', (e) => {
console.log('popstate', e);
changeContent()
})
</script>
</body>
</html>