路由的概念起源于网络工程,例如我们日常中的路由器,所谓前端路由的概念简单归纳就是前端可以自己根据不同url地址来展示不同的内容
在Ajax
出现之前,都是使用后端路由来控制页面的渲染,服务器在接收到不同的url
地址后,服务器通过解析url
去拼接不同的html
,然后返回给前端进行渲染,所以这也是后端路由的一个弊端,每一次的切换都是需要刷新整个页面,同时如果是大量的页面每一个页面都需要做一段逻辑处理也造成了后端实在不堪重负
前端路由的出现很好的解决了这个问题,前端路由不需要刷新整个页面,也就不会出现每一次切换都会出现闪烁,也没有网络延迟,大大提升了用户体验,减轻了服务器的压力,但是同时也存在问题是前端的安全性问题
目前前端路由的实现主要采用两个方法
- hash
- history
hash
hash就是我们通常说的锚点,一般用于内容的快速定位,但是hash值有一个特点,就是会改变url,但是不会触发浏览器的刷新,利用这个特点,我们配合可以检测到hash值变化的hashchange
事件就能比较容易实现前端路由
window.addEventListener("hashchange",function () { console.log("锚点值改变了"); //发送ajax请求,局部刷新页面,加载模块等操作})
history
history是window
对象的一部分,包含用户在浏览器中访问过的历史记录
-
属性
length:该属性会返回浏览器中历史记录的数量
state:返回一个历史记录中顶部记录的状态值
scrollRestoration:允许浏览器自定义设置默认的滚动行为,该属性有两个值,auto和manual
这里关于
scrollRestoration
属性我们多说一点,在JavaScript中有一个叫做scrollTo
的方法,该方法可以指定滑动位置,例如可以用来控制我们每一次聊天内容都固定在窗口的底部test.scrollTo(0,test.scrollHeight)
但是有时候并不会生效,这个有可能就是
scrollRestoration
的原因,因为浏览器是默认保持滚动位置的,也就是说浏览器设置history
的默认值是auto
,我们需要将其设置为manual
history.scrollRestoration="manual"
这个是时候就可以正常的按照我们的需求每一次固定到窗口底部了
如果有兼容性问题采用如下写法
setTimeout(() => { window.scrollTo(0, document.body.scrollHeight)})
- 方法
back:返回上一条历史记录
forward:前往下一条历史记录
go:前往指定的历史记录,history.go(1)相当于history.forward(),history.go(-1)相当于history.back()
同时在js中也存在一个popstate
的方法可以监测到浏览器的前进/后退,同时在该方法中可以获取到历史记录的状态对象
window.addEventListener("popstate",function (e) { console.log(e.state)})
在HTML5中新增加了两个方法pushState,replaceState
这两个方法都是在不触发浏览器的刷新机制下改变浏览器的url
,不同之处在于pushState
相当于在浏览器历史记录栈中添加了一条我们自定义的历史记录,而replaceState
相当于用我们自己设置的历史记录替换掉了浏览器当前的历史记录栈中的第一条,所以pushState
会改变history
的length
长度,而replaceState
则不会
这两个方法都接收三个参数
- state,一个指定网址相关的状态对象
- title,指定新页面的标题,但是目前被大部分浏览器忽略
- url,指定新的网址,但是必须是和当前网址是同源的
这两个方法都是不能被popstate监测到的,但是在执行两个方法的时候是能够触发history.state的从而我们可以拿到我们每一次增加/替换历史记录时的state
,可以通过观察者模式来实现对history
状态的监听
let page=1ahead.addEventListener("click",function () { page++; window.history.pushState({page : page}, 'test', '#test'); console.log(window.history.state); //通过state值可以加载不同模块/发送数据请求,局部刷新页面})window.addEventListener("popstate",function (e) { console.log(e.state) //在用户点击后退、前进时会被postate监测到,同时也会获取到state })