这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战
TIP 👉 临渊羡鱼,不如退而结网。《汉书·董仲舒传》
前言
早些时候,当时前后端还是不分离的,路由都由服务端控制。
客⼾端 -> http 请求 -> 服务端 -> 根据 url 路径的不同,返回不同的 html/数据
这种⽅式的缺点和优点都⾮常明显
优点:SEO 效果好, ⽤⼾看到⾸屏的耗时会⾮常⼩
缺点:服务器压⼒⼤,代码融合在⼀起不好维护,协作流程不清晰
随之 ajax 的流⾏,异步数据请求可以在浏览器不刷新的情况下进⾏。出现了更⾼级的体验 - 单⻚应⽤。在单⻚应⽤中,不仅在⻚⾯中的交互是不刷新⻚⾯的,就连⻚⾯跳转也都是不刷新⻚⾯的。⽽⽀持起单⻚应⽤这种特性的,就是前端路由。
前端路由特性
前端路由的需求是什么?
1.根据不同的 url 渲染不同内容
2.不刷新⻚⾯
也就是可以在改变 url 的前提下,保证⻚⾯不刷新。
Hash原理及实现
hash 的出现满⾜了这个需求,他有以下⼏种特性:
-
url 中的 hash 值只是客⼾端/浏览器端的⼀种状态,向服务器发送请求的时候,hash 部分的值不会携带。
-
hash 值的更改,并不会导致⻚⾯的刷新
-
hash 值的更改,会在浏览器的访问历史中增加记录,所以我们可以通过浏览器的回退、前进按钮控制 hash 的切换
-
hash 值的更改,会触发 hashchange 事件⽐如www.baidu.com/#/hash1, 改变#后⾯的内容并不会导致⻚⾯刷新,⽽且会触发hashchange 事件。
我们同样有两种⽅式来控制 hash 的变化:
-
通过 a 标签,设置 href 属性,当⽤⼾点击 a 标签的时候,Url 中的 hash 就会改变为 href 属性值。⽐如 点击更改 hash
-
通过 js
location.hash = '#hash-change'
History原理及实现
hash 虽然能解决问题,但是带有#很不美观。
历史的⻋轮⽆情撵过 hash,到了 html5 时代,推出了 history api。
-
window.history.back(); // 后退
-
window.history.forward(); // 前进
-
window.history.go(-3); // 后退三个⻚⾯
-
window.history.pushState(null, null, path);
-
window.history.replaceState(null, null, path);
其中最主要的两个 api 是 pushState和replaceState;
这两个 api 都可以在不刷新⻚⾯的情况下,操作浏览器历史记录。
不同的是,pushState会增加历史记录,replaceState会直接替换当前历史记录。
History Api 有以下⼏种特性:
-
history.pushState()或history.replaceState()不会触发popstate事件,这时我们需要⼿动触发⻚⾯渲染; -
可以使⽤
popstate事件来监听 url 的变化 -
只有⽤⼾点击浏览器倒退按钮和前进按钮,或者使⽤
JavaScript调⽤back、forward、go⽅法时才会触发popstate。
他们的参数是⼀样的,三个参数分别是:
-
state:⼀个与指定⽹址相关的状态对象,popstate事件触发时,该对象会传⼊回调函数。如果不需要这个对象,此处可以填 null。 -
title:新⻚⾯的标题,但是所有浏览器⽬前都忽略这个值,因此这⾥可以填null。 -
url:新的⽹址,必须与当前⻚⾯处在同⼀个域。浏览器的地址栏将显⽰这个⽹址。