react router原理探究(简版)
本文最后更新于:2 个月前
react router路由切换原理探究(简版)
在 Web 前端单页面应用 SPA(Single Page Application)中,路由是描述 URL 和 UI 之间的映射关系,这种映射是单向的,即 URL 的改变会引起 UI 更新,无需刷新页面
根据上面这段话,可以得到,react想要实现路由页面切换需要完成3点:
- 引起URL的变化,并能够体现在浏览器的地址栏上
- URL的变化,不能引起整个页面的刷新
- URL的变化,需要引起局部UI(组件)的刷新
一、前置知识
前端路由有2种模式,hash 和 history
1、hash模式
1 |
|
在浏览器中,打开改html文件,分别点击两个链接,可以看到视图中内容发生变化。同时浏览器不会重新发出资源请求。
hash模式的优缺点:
- 优点:兼容性好
- 缺点:路径在
#
后面比较丑;在 SEO 中有不好的影响
2、history模式
history API 是 H5 提供的新特性,允许开发者直接更改前端路由,即更新浏览器 URL 地址而不重新发起请求。
history对象一共有5个方法:
back()
,返回上一页forward()
,进入浏览历史的下一页(如果有的话,即使没有也不报错)go()
,跳转到浏览历史的指定部分,go(1)
等价于forward()
,go(-1)
等价于back()
pushState(state, unused, [url])
,向浏览器的会话历史栈增加一条记录。这个方法比较重要,下面会详细介绍。replaceState(state, unused, [url])
,修改当前历史记录条目的状态对象 or URL,与pushState()
相似
popstate事件
每当激活同一文档中不同的历史记录条目时,popstate
事件就会在对应的 window
对象上触发。
点击浏览器的「后退」、「前进」按钮会触发,调用history对象的back()
、forward()
、go()
这3个方法也会触发popstate事件;但调用pushState()
和replaceSate()
不会触发popstate事件!
pushState()
1 |
|
state
是一个js对象,调用后换传递给history.state,通常传递一个空对象{}
;unused
,由于历史原因,该参数不再使用但不能忽略,通常传递null
;[url]
,[]
表示可选,新历史条目的url- 调用 pushState() 后,浏览器不会加载该URL,但它会在用户重启浏览器、会点击浏览器刷新按钮之后加载该URL;
- url可以是绝对路径;也可以是相对路径,相对路径将基于当前的URL进行解析;
- 传入的url必须与原先的url同源,否则将抛出异常;
- 如果url没有指定,相当于设置为当前的url;
- 该方法不会触发
popstate
事件。
示例
1 |
|
(ps:需要使用light-server
模块构造出一个本地服务器来打开html,light-server -s . --historyindex '/history.html' --port 3000
。如果本地直接打开html,url无法按照预期效果生效,如下)
实测发现,<a href="#/c">c页面</a>
这种方式也能触发 popstate
事件
优缺点
- 优点:url整体美观规范
- 缺点:兼容性比hash差;需要服务端支持SPA的History API模式
扩展:light-server的作用
官方文档:light-server - npm (npmjs.com)
在上面history的演示中,对light-server
模块最核心使用的功能是History API模式。由参数--historyindex
指定。
1 |
|
其实 History API 模式的原理很简单!它所做的就是在服务器上添加一个简单的回退路由。如果 URL 不匹配任何静态资源,它应提供与你的应用程序中的 index.html 相同的页面。
二、如何引起URL变化
如【前置知识】介绍,通过改变hash、调用history对象的方法这两种方式,都可以改变浏览器URL框中的 URL,而同时不会触发页面的重新请求。
hash方式
1 |
|
history API方式
1 |
|
三、URL的变化如何触发UI更新
正如前面所言,不管是hash的变化,还是调用history API,浏览器都不会重新发出资源请求。
但同时,我们可以注意到通常SPA的路由切换之后,浏览器都会重新发出一堆对.js
、.css
等文件的请求,那么这些请求又是由哪里操作发出的呢?
另外,页面UI是如何随着 URL 的变化同步刷新的呢?