0%

vue-router中hash模式和history模式区别

vue-router的本质:

路由就是SPA(单页应用)的路径管理器,vue-router的单页应用中,则是路径之间的切换,也就是组件的切换,路由模块的本质就是建立起url和页面之间的映射关系

为什么不能用a标签,这是因为Vue左的是单页应用,当你的项目准备打包时,会生成dist文件夹,这里面只有静态资源和一个index.html页面,所有a标签跳转页面不起作用

单页应用的核心之一就是:更新视图而不重新请求页面,vue-router在实现单页面前端路由时,提供两种方式:Hash模式和History模式,根据mode参数来决定使用哪一种

Hash模式

vue-router默认hash模式,使用URL的hash模拟一个完整的URL,于是URL改变时,页面不会重新加载,hash(#)是URL的锚点,代表网页中的一个位置,单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载页面,也就是hash出现在URL中(#后面的值),但不会被包含在http请求中,对后端没有影响,因此改变hash不会重新加载页面;同时每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用“后退”按钮,就可以回到上一个位置,所以Hash模式通过锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据,hash模式原理是onhashchange事件(监测hash值变化),可以在window对象上监听这个事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
class Router{
constructor(){
//存储hash与callback键值对
this.routes={};
//当前hash
this.currentUrl="";
//记录出现过的hash
this.history=[];
//作为指针,默认指向this.history的末尾,根据后退前进指向history中不同的hash
this.currentIndex=this.history.length-1;
this.refresh=this.refresh.bind(this);
this.backoff=this.backoff.bind(this)
//默认不是后退操作
this.isBack=false
window.addEventListener('load',this.refresh,false)
window.addEventListener('hashchange',this.refresh,false)


}
route(path,callback){
this.routes[path]=callback||function(){}
}
refresh(){
//不能包括'#'
this.currentUrl=location.hash.slice(1)||'/';
//不是后退操作
if(!this.isBack){
//如果当前指针小于数组总长度,直接截取之前的部分储存下来,避免点击后退按钮后指针后移一位,当再次正常跳转时,指针前进一位,
//而在数组中添加新hash路由
//导致指针和路由不匹配
if(this.currentIndex<this.history.length-1){
this.history=this.history.slice(0,this.currentIndex+1)

}
this.history.push(this.currentUrl)
this.currentIndex++;
}
this.routes[this.currentUrl]()
this.isBack=false;
}
backoff(){
this.isBack=true
this.currentIndex<=0
?(this.currentIndex=0)
:(this.currentIndex=this.currentIndex-1)
//找到后退后的哈希地址
location.hash=`#${this.history[this.currentIndex]}`
//调用后退后的地址对应的函数
this.routes[this.history[this.currentIndex]]
}

}
window.Router=new Routers()
const content=document.querySelector('body')
const button=document.querySelector('button')
function changeBgColor(color){
content.style.background=color
}
Router.route('/blue',function(){
changeBgColor('blue')
})
Router.route('/green',function(){
changeBgColor('green')
})
Router.route('/red',function(){
changeBgColor('red')
})
button.addEventListener('click',Router.backoff,false)

history模式

hash模式在url中自带#,比较丑,可以用路由的history模式,只需要在配置路由规则时,加上’mode:history’

这种模式利用了html5 history Interface中新增的pushState()和replaceState()方法,这两个方法应用于浏览器记录栈,在当前已有的back,forwarc,go基础上,它们提供了对历史记录修改的功能,只是当修改时,虽然改变了当前的URL,但浏览器不会去请求服务器该路径下的资源,一旦刷新就会暴露,显示404,因此这种模式下需要后端的支持,在服务端增加一个覆盖所有情况的候选资源:如果URL匹配不到任何静态资源,就返回一个Index.html页面,这个页面就是app依赖的页面

export const routes=[

​ {path:”*”,redirect:’/‘}

]

history.pushState用于在浏览器中添加历史记录,但不触发跳转,此方法接收三个参数:

  • state:一个与指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数,不需要这个对象时此处就填null

  • title:新页面标题,但是所有浏览器目前都忽略这个值,因此这里填null

  • url:新的网址,必须与当前页面处在同一个域,浏览器的地址栏将显示这个网址

    新标准下路由的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Router{
constructor(){
this.routes={};
this.bindPopState();
}
init(path){
history.replaceState({path:path},null,path)
this.routes[path]&&this.routes[path]()
}
route(path,callback){
this.routes[path]=callback||function(){}
}
go(path){
history.pushState({path:path},null,path)
this.routes[path]&&this.routes[path]()
}
_bindPopState(){
window.addEventListener('popstate',e=>{
const path=e.state&&e.state.path;
this.routes[path]&&this.routes[path]()
})
}
}
window.Router = new Routers();
Router.init(location.pathname);
const content = document.querySelector('body');
const ul = document.querySelector('ul');
function changeBgColor(color) {
content.style.backgroundColor = color;
}

Router.route('/', function() {
changeBgColor('yellow');
});
Router.route('/blue', function() {
changeBgColor('blue');
});
Router.route('/green', function() {
changeBgColor('green');
});