什么是路由

spa应用,都是前端路由,其他是后端路由

前端路由与后端路由的优劣势

  1. 后端路由优点是:安全性好,SEO好。缺点是:加大服务器的压力,不利于用户体验,代码冗合
  2. 前端的路由就是优点是:前端路由在访问一个新页面的时候仅仅是变换了一下路径而已,没有了网络延迟,对于用户体验来说会有相当大的提升。缺点是:使用浏览器的前进,后退键的时候会重新发送请求,没有合理地利用缓存,同样的不利于seo

前端路由有几种方案

  1. hash
  2. history Api

实现原理

hash实现原理

hash实现就是基于location.hash来实现的。其实现原理也很简单,location.hash的值就是URL中#后面的内容。

1
https://www.aaa.com/#abcsdf

我们可以使用hashchange事件来监听hash的变化。并且通过history.length能看到路由总数

用hash的方案实现一个路由切换
1
2
3
4
5
6
7
//首先我们要有个html
<ul>
<li><a href="#luyou1">路由1</a></li>
<li><a href="#luyou2">路由2</a></li>
<li><a href="#luyou3">路由3</a></li>
</ul>
<div id="luyouid"></div>
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
//ts逻辑
class router {
//存贮当前路由
hashStr: String;
constructor(hash: String) {
//初始化赋值
this.hashStr = hash;
//初始化
this.watchHash();
//绑定监听改变事件,由于this被换了,必须用bind绑定
this.watch = this.watchHash.bind(this);
window.addEventListener("hashchange", this.watch);
}
//监听方法
watchHash() {
console.log();
let hash: String = window.location.hash.slice(1);
this.hashStr = hash;
console.log(hashStr);
if (hashStr) {
if (hashStr == "luyou1") {
document.querySelector("#luyouid").innerHTML = "aaa";
} else if (hashStr == "luyou2") {
document.querySelector("#luyouid").innerHTML = "bbb";
} else {
document.querySelector("#luyouid").innerHTML = "ccc";
}
}
}
}

history实现原理

history 这个对象在html的时候新加入两个api history.pushState() 和 history.repalceState()
这两个 API可以在不进行刷新的情况下,操作浏览器的历史纪录。唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录。

API使用
1
2
3
4
5
6
7
8
9
10
11
12
13
window.history.pushState(state,title,url)
//state:需要保存的数据,这个数据在触发popstate事件时,可以在event.state里获取
//title:标题,基本没用,一般传null
//url:设定新的历史纪录的url。新的url与当前url的origin必须是一样的,否则会抛出错误。url可以时绝对路径,也可以是相对路径。
//如 当前url是 https://www.baidu.com/a/,执行history.pushState(null, null, './qq/'),则变成 https://www.baidu.com/a/qq/,
//执行history.pushState(null, null, '/qq/'),则变成 https://www.baidu.com/qq/

window.history.replaceState(state,title,url)
//与pushState 基本相同,但她是修改当前历史纪录,而 pushState 是创建新的历史纪录

window.history.back()//后退
window.history.forward()//前进
window.history.go(1)//前进一部,-2回退两不,window.history.length可以查看当前历史堆栈中页面的数量
监听history

同一个文档的浏览历史(即history)出现变化时,就会触发popState事件,只要我们监听事件

1
2
window.addEventListener('popstate', function(event) {
});

仅仅调用pushState方法或replaceState方法,并不会触发该事件,只有用户点击浏览器后退和前进按钮时,或者使用js调用back、forward、go方法时才会触发。

监听 pushState 和 replaceState 的变化

我们可以创建2个全新的事件,事件名为pushState和replaceState,我们就可以在全局监听

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//创建全局事件
var _wr = function(type) {
var orig = history[type];
return function() {
var rv = orig.apply(this, arguments);
var e = new Event(type);
e.arguments = arguments;
window.dispatchEvent(e);
return rv;
};
};
//重写方法
history.pushState = _wr('pushState');
history.replaceState = _wr('replaceState');
//实现监听
window.addEventListener('replaceState', function(e) {
console.log('THEY DID IT AGAIN! replaceState 111111');
});
window.addEventListener('pushState', function(e) {
console.log('THEY DID IT AGAIN! pushState 2222222');
});