什么是路由
spa应用,都是前端路由,其他是后端路由
前端路由与后端路由的优劣势
- 后端路由优点是:安全性好,SEO好。缺点是:加大服务器的压力,不利于用户体验,代码冗合
- 前端的路由就是优点是:前端路由在访问一个新页面的时候仅仅是变换了一下路径而已,没有了网络延迟,对于用户体验来说会有相当大的提升。缺点是:使用浏览器的前进,后退键的时候会重新发送请求,没有合理地利用缓存,同样的不利于seo
前端路由有几种方案
- hash
- 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'); });
|