url的构成
https://example.com:8080/path/to/resource?param1=value1¶m2=value2#section1
// 获取完整的URL https://example.com:8080/path/to/resource?param1=value1¶m2=value2#section
var url = new URL('https://example.com:8080/path/to/resource?param1=value1¶m2=value2#section')
var href = url.href;
// 获取协议 https:
var protocol = url.protocol;
// 获取域名 example.com
var domain = url.hostname;
// 获取端口 8080
var port = url.port;
// 获取路径 /path/to/resource
var path = url.pathname;
// 获取查询参数 ?param1=value1¶m2=value2'
var queryParams = url.search;
// 获取哈希值 #section1
var hash= url.hash;
hash模式
在hash模式下,URL的格式为http://example.com/#/path,其中path代表不同的路由路径。当浏览器URL中的hash发生变化时,通过监听hashchange事件来触发相应的路由变化。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="content"></div>
<div id="index">首页</div>
<div id="nav1">导航1</div>
<div id="nav2">导航2</div>
<script>
const routers = [
{
path: '/index',
content: '<h1>首页</h1>',
},
{
path: '/nav1',
content: '<h1>导航1</h2>',
},
{
path: '/nav2',
content: '<h1>导航2</h1>',
},
]
window.onhashchange = function () {
// 在这里处理哈希变化的逻辑
changeRouter()
}
index.addEventListener('click',()=>{
window.location.hash = '/index'
})
nav1.addEventListener('click',()=>{
window.location.hash = '/nav1'
})
nav2.addEventListener('click',()=>{
window.location.hash = '/nav2'
})
function changeRouter() {
const hash = window.location.hash
const path = hash.replace('#', '')
const router = routers.find((router) => router.path === path)
if (router) {
content.innerHTML = router.content
return
}
content.innerHTML = '<h1>404</h1>'
}
changeRouter()
</script>
</body>
</html>
点击按钮时,会触发window.location.hash = '/index'改变url的hash值,从而触发onhashchange 事件。在onhashchange 事件中获取hash值来改变页面的内容。
hash地址的变化并不会发送网络请求,页面的改变完全是由前端页面完成的。
history模式
Vue Router 的history模式(History Mode)是基于 HTML5 的 History API 实现的。通过调用 pushState 或 replaceState 方法来修改浏览器的历史记录,并更新当前的路由状态。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="content"></div>
<div id="index">首页</div>
<div id="nav1">导航1</div>
<div id="nav2">导航2</div>
<script>
const routers = [
{
path: '/index',
content: '<h1>首页</h1>',
},
{
path: '/nav1',
content: '<h1>导航1</h2>',
},
{
path: '/nav2',
content: '<h1>导航2</h1>',
},
]
function renderRoute() {
const path = window.location.pathname
const router = routers.find((router) => router.path === path)
const content = document.getElementById('content')
if (router) {
content.innerHTML = router.content
} else {
content.innerHTML = '<h1>404</h1>'
}
}
window.onpopstate = function (event) {
console.log('popstate 事件触发', event.state)
renderRoute()
}
index.addEventListener('click', () => {
window.history.pushState(null, null, '/index')
renderRoute()
})
nav1.addEventListener('click', () => {
window.history.pushState(null, null, '/nav1')
renderRoute()
})
nav2.addEventListener('click', () => {
window.history.pushState(null, null, '/nav2')
renderRoute()
})
</script>
</body>
</html>
pushState和replaceState 仅仅是对浏览器的历史记录进行更改,url会被改变,但是浏览器不会进行刷新也不会向后端发送网络请求(路由没有使用懒加载),但是会触发代码内部的监听事件从而更新页面内容,单纯的进行页面的切换不需要依赖服务器。
但是随着历史记录的更改,会产出新的url,这时候进行页面的刷新,浏览器会向服务器请求新的url,导致服务器返回 404 错误。因此服务器需要正确配置以确保在访问任何路径时都返回同一个 HTML 页面,从而避免服务器返回 404 错误。