由于 Vuc 项目为单页面应用,所以整个项目在开发和构建过程中,仅存在一个 HTML物理文件。通过路由系统可以实现将项目的组件与可访问的 URL 路径进行绑定。由于 Vue项目只有一个 HTML 物理文件,切换页面时既需要让访问的 URL 路径发生变化,又不能触发HTML 物理文件的重新加载,这就使得 VueRouter 的跳页模式不能使用普通的超链接方式。
VueRouter 为了支持单页面应用的页面管理和页面跳转,提供了两种页面的跳转和加载模式:
(1)hash模式
hash 模式使用了锚点技术重写URL访问路径,会在原有的 URL 路径后拼接/#/xxx,这种方式可以在不重新加载原有 HTML 文件的基础上,实现切换 URL 路径的目的。hash 模式的原理实现案例,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hash模式的路由</title>
<style>
.page {
width: 400px;
height: 400px;
}
.about {
background-color: antiquewhite;
display: none;
}
.index {
background-color: antiquewhite;
display: none;
}
</style>
</head>
<body>
<a href="#/index">访问首页</a>
<a href="#/about">访问关于原页面</a>
<div class="page index">
我是首页
</div>
<div class="page about">
我是关于页面
</div>
<script type="text/javascript">
// url的hash部分切换事件
window.onhashchange = function (event) {
// 写两个的意思是跳转的时候新的显示,旧的隐藏
// 获取要跳转的url路径并截取页面名称
var newURL = event.newURL.split('#/')[1]
// 获取跳转时的起点页面路径并截取页面名称
var oldURL = event.oldURL.split('#/')[1]
// 获取两个页面的dom对象
var newPage = document.querySelector('.'+newURL)
var oldPage = document.querySelector('.'+oldURL)
// 显示目标页面
newPage.style.display = 'block'
// 隐藏当前页面
oldPage.style.display = 'none'
}
</script>
</body>
</html>
hash 模式利用了纯静态技术,解决了单页面应用的页面划分,它可以在不触发网页重新加载的情况下切换 URL路径,配合 onhashchange()可以实现,一旦 URL中的 hash 部分发生变化,就触发函数通知,通过 JavaScript 编程便可以很快速的实现 DOM 对象的切换展示。hash 模式同时也存在不足之处,如在分布式微前端项目中,嵌套的子应用和主应用都使用用hash 模式时,由于 hash 模式的 URL 路径只能存在一个#,会导致子应用和主应用在定义URL路上存在困难hash 模式的URL路径中包含#,也会在视觉上导致URL路径不美观。
注:分布式微前端:就是前端每个人写一个项目,他还是一个项目,网页要部署在不同的服务器上,用户访问的时候还感觉不出来。如果有多个项目互相合作使用hash模式,会导致#位置不一样,使项目配合出现问题。
可以通过 给location.hash 赋值 改变 hash
location.hash = '/about'
通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变
<a href="#/hash">去hash页面</a>
通过$router.push方法,会改变hash值触发hashchange事件,前进到指定的url
this.$router.push('/')
hash 路由模式的实现主要是基于下面几个特性:
- URL 中 hash 值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送;
- hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换;
- 可以通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用 JavaScript 来对 loaction.hash 进行赋值,改变 URL 的 hash 值;
- 我们可以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。
(2)history模式
history 模式是 VueRouter 中常用的一种路由模式,它与 hash 模式不同,不需要借助错点技术重写URL路径,所以 history 模式使用的 URL 路径中不存在#,在视觉上更加美观, 利用H5的 history中新增的两个API pushState() 和 replaceState() 和一个事件onpopstate监听URL变化。 history 模式采用 history 对象中的 pushState()函数重写URL路径,可在触发重新加载的情况下变更URL路径,history 模式的原理,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>history模式</title>
<style>
.page {
width: 400px;
height: 400px;
}
.about {
background-color: antiquewhite;
display: none;
}
.index {
background-color: antiquewhite;
display: none;
}
</style>
</head>
<body>
<!-- 定义路由菜单 -->
<!-- 利用点击事件 -->
<a href="javascript:jump('/index')">跳转到index页面</a>
<a href="javascript:jump('/about')">跳转到about页面</a>
<!-- 定义页面结构 -->
<div class="page index">
我是index页面
</div>
<div class="page about">
我是about页面
</div>
<script type="text/javascript">
// 跳转函数
function jump(path){
history.pushState(null,'page',path)
// 获取所有页面组件
var pages = document.querySelectorAll('.page')
// 获取指定跳转的目标页面对象
var newPage = document.querySelector(path.replace('/','.'))
// 隐藏其他页面
pages.forEach(item => item.style.display = 'none')
// 展示跳转的页面
newPage.style.display = 'block'
}
</script>
</body>
</html>
history 模式重写 URL 路径的解决方案与 hash 式现象类似但本质不同,虽然 history模式可以重写URL路径,但是重写后的新路径中并不包含原有 HTML物理文件的访问地址,所以 history 模式在重写 URL 路径后,一旦刷新网页会造成404 无法访问的效果。VueCLI在开发环境中解决了 history 模式的刷新问题,不过项目发布到生产环境时,由于 history 模式的 URL路径问题,还需要配合生产服务器的转发规则重写,用以支持 history 模式的路由加载。
history.pushState() 和 history.repalceState()。这两个 API 可以在不进行刷新的情况下,操作浏览器的历史纪录。唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录,如下所示:
window.history.pushState(null, null, path); // 新增一个历史记录
window.history.replaceState(null, null, path); // 直接替换当前的历史记录
history.pushState(data, title, targetURL)
参数:
- 状态对象:传给目标路由的信息,可为空
- 页面标题:目前所有浏览器都不支持,填空字符串或者null即可
- 可选url:目标url,不会检查url是否存在,且不能跨域。如不传该项,即给当前url添加data
window.history.replaceState(data, title, targetURL)
- @类似于pushState,但是会直接替换掉当前url,而不会在history中留下记录
以这个链接为例 http://localhost:8080/#/
1、相同点
都不支持跨域
2、不同点
是否会留下记录
(1)history.pushState
可以用back 说明有留下记录。
(2)history.reloaceState
无法back,因为没有留下记录。
注:javascript 中的location.pathname
分析下面的URL: http://www.joymood.cn:8080/test.php?user=admin&pwd=admin#login
- location.href:得到整个如上的完整url
- location.protocol:得到传输协议 http:
- location.host:得到主机名连同端口 www.joymood.cn:8080
- location.hostname:得到主机名 www.joymood.cn
- location.pathname:得到主机后部分不包括问号?后部分的 /test.php
- location.search:得到url中问号?之后井号#之前的部分 ?user=admin&pwd=admin
- location.hash:得到#及之后的部分 #login
“在 VueCLI项目中,可以通过 mode 属性来切换路由的 history 模式和 hash 模式。
在vue2中切换详解vue cli2.0路由的hash模式和history模式的打包并查看本地效果的方法-CSDN博客
在vue3中实现切换