START
- 番茄也写一写,前端路由的两种模式
- 时间仓促,能力有限,难免有言语不当之处,望指正。
后端路由
-
我最早接触路由这个概念呢,是在学习
node.js
的时候。使用node.js
搭建一个后端服务,通过在后端服务配置不同的路由地址,浏览器请求这些地址。来获取各种内容(例如html,txt,json
等).我眼中的路由呢,就好像是一种路径/地址,方便我们依据路径去寻找到对应的资源,仅此而已。
-
早期的一些网站,就是用的后端路由,每点击一个菜单,就会切换一个
url
地址,来拿到不同的html
以及其他资源展示出来。http://lazy_tomato/home => 获取并展示home页面
http://lazy_tomato/sayHello => 获取并展示sayHello页面
总结一下
后端路由:每次切换
url
,会刷新页面,加载新的页面和资源。
前端路由
前端页面发展的历程
- 最初是后端把页面都处理好,直接返回给浏览器;
- 然后出现了ajax,页面上一部分交互是使用ajax去实时刷新的;
- 然后开始流行前端三大框架,然后开始流行单页面应用;
单页面应用(single page web application),简称SPA。
单页面应用,只有一个主页面,但是功能的切换,需要
hash history
配合实现。
前端路由的工作方式
-
用户点击了页面上的路由链接;
-
导致了
url
地址栏中的值发生了变化,但是页面不会刷新(利用了hash history
实现); -
前端路由监听了地址的变化;
-
前端路由把当前地址对应的组件渲染都浏览器中;
本质上,其实就是浏览器的url
变化,不刷新浏览器,切换页面展示。hash / history
就可以实现我们这一要求。
1.hash
hash
最明显的特点就是url
中有一个#
号。
例如:
https://www.baidu.com/#tomato
可以尝试一下啊,随便找个网址,在
url
最后面添加#
和任意字符。发现在控制台的network
中并不会加载数据和页面。
怎么获取url
上的hash
值?可以通过location.hash
去获取
location.hash // '#tomato'
怎么去监听hash
的变化呢?
// 借助事件 `hashchange`
window.addEventListener('hashchange', event => {
console.log(event)
})
测试截图如下:
2.history
除了hash
模式,还有一种模式: history
模式 ,它也可以改变url
,但不刷新页面。
我们可以在浏览器中 使用 window.history
打印一下它。又或者去MDN官网查看一下history
中包含那些属性和方法。
// 属性
history.length // 表示会话历史中元素的数目,包括当前加载的页。
History.state // 返回一个表示历史堆栈顶部的状态的值
// 方法
History.pushState() // 按指定的名称和url(如果提供该参数)将数据push进会话历史栈。 简单理解添加一个路径。
History.replaceState() // 按指定的数据,名称和url(如果提供该参数),更新历史栈上最新的入口。
History.back() // 返回一级
History.forward() // 前进一级
history.go(-1) // go(0) 刷新页面 正数=>前进几级; 负数=>后退几级; 如果超过边界,不报错也不执行。
浏览器控制台上尝试一下这几个方法
表格可能看起来比较冗余,可以跳过这个表格,这个表格只是记录了一下我熟悉
history
上的方法时,运行的结果。
浏览器的url | 控制台输入命令 | 输入命令后的url |
---|---|---|
https://www.baidu.com/ | history.pushState({},'','a1') | https://www.baidu.com/a1 |
https://www.baidu.com/a1 | history.pushState({},'','a2') | https://www.baidu.com/a2 |
https://www.baidu.com/a2 | history.pushState({},'','a3') | https://www.baidu.com/a3 |
https://www.baidu.com/a3 | history.pushState({},'','a4') | https://www.baidu.com/a4 |
https://www.baidu.com/a4 | history.back() | https://www.baidu.com/a3 |
https://www.baidu.com/a3 | history.forward() | https://www.baidu.com/a4 |
https://www.baidu.com/a4 | history.go(-2) | https://www.baidu.com/a2 |
https://www.baidu.com/a2 | history.replaceState({},'','replacePage') | https://www.baidu.com/replacePage |
https://www.baidu.com/replacePage | history.back() | https://www.baidu.com/a1 |
https://www.baidu.com/a1 | history.forward() | https://www.baidu.com/replacePage |
https://www.baidu.com/replacePage | history.forward() | https://www.baidu.com/a3 |
怎么去监听history
的变化呢?
window.onpopstate = function(){
console.log(arguments)
}
运行截图
总结:
可以自己去浏览器打印一下这几个方法,其实就一个容器,然后通过自带的方法,加减历史记录栈,此处加减规则为先进后出。
3.hash和history的相同点和不同点
相同点
- 都可以不刷新页面,切换
url
。
不同点
-
hash
模式有#
;history
没有; -
hash
只可修改url
中#
后面的部分;history
设置新url
可以是与当前url
同源的任意url
; -
hash
模式下出现在url
中#
后面的部分,不会被包括在HTTP请求中,对后端没有影响,不会重新加载页面;history
模式下,前端的url
必须和实际向后端发起请求的url
一致,若刷新页面,后端路由未处理,将返回404错误。如果是部署在
nginx
上的话,可以进行如下处理# 添加一个配置即可 try_files $uri $uri/ /index.html; # 1.记住不要找错配置文件; 2.不要忘记重启nginx。 server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root html/dist; index index.html index.htm; # !!针对 history模式的单页面应用,刷新404的问题 try_files $uri $uri/ /index.html; } }
-
hash
只可添加短字符串;history
通过pushState()
第一个参数可以添加任意类型的数据到记录中;
vue-router
源码解读
后续补充
END
- 到这里基本上,路由两种模式都理解的很透彻了。
- 作者:番茄
- 编写时间:2022/04/28-20/24