学习资料:拉勾课程《大前端高薪训练营》
一:前端路由的通信逻辑原理
本质逻辑:操作浏览器 / 元素事件 / 编程式导航 -> 浏览器路由变化 + 程序页面更新
操作浏览器是指页面刷新,页面前进后退,手动改变浏览器url等会改变浏览器路由的操作
二:hash模式的路由通信逻辑实现
1.通信原理
下面是hash模式对操作浏览器 / 元素事件 / 编程式导航 -> 浏览器路由变化 + 程序页面更新这个前端路由逻辑的实现思路。
操作浏览器
- 操作浏览器 -> 浏览器路由变化:浏览器自动完成,路由中变化的是锚点
- 操作浏览器 -> 程序页面 / 组件更新:操作浏览器导致浏览器路由变化后,触发程序中注册的hashchange事件,进而程序根据路由找到组件,页面更新。
hashchange事件:当URL的片段标识符更改时,将触发hashchange事件 (跟在#符号后面的URL部分,包括#符号)
元素事件
- 元素事件 -> 浏览器路由变化:如<a href ="#/home">xx<a>标签点击后,路由中的锚点变化为href属性值/home
- 元素事件 -> 程序页面 / 组件更新:元素事件触发导致浏览器路由变化后,触发程序中注册的hashchange事件,进而程序根据路由找到组件,页面更新。
编程式导航
- 编程式导航 -> 浏览器路由变化:如 location.href = “xxx/#/home”,路由中的变化为/home
- 编程式导航 -> 程序页面 / 组件更新:编程式导航命令导致浏览器路由变化后,触发程序中注册的hashchange事件,进而程序根据路由找到组件,页面更新。
2.案例
如下是元素事件方式切换路由的案例
<a href="#/home">首页</a> <!-- 元素事件 -> 浏览器路由变化 -->
<a href="#/about">关于</a>
<div id="html"></div>
<script>
window.addEventListener('load',()=>{
html.innerHTML = location.hash.slice(1);
});
// 元素事件 -> 程序页面 / 组件更新
window.addEventListener('hashchange',()=>{
html.innerHTML = location.hash.slice(1)
})
<script>
三:history模式的路由通信逻辑实现
注意:history模式需要用到H5的api,所以会有浏览器兼容问题。
1.通信原理
下面是history模式对操作浏览器 / 元素事件 / 编程式导航 -> 浏览器路由变化 + 程序页面更新这个前端路由逻辑的实现思路。
操作浏览器
- 操作浏览器 -> 浏览器路由变化:浏览器自动完成,路由中变化的是同域下的不同路径
- 操作浏览器 -> 程序页面 / 组件更新:操作浏览器触发程序中注册的popstate事件,进而程序根据路由找到组件,页面更新。
注意:操作浏览器(前进、后退、刷新、输入url等)会导致浏览器url路径变化从而向后端发起请求,发生404问题。这里我们需要明确一点,我们想要的是前端路由匹配而不是后端路由匹配,所以需要在后端配置404时回到首页(如express use history,nginx配置try_file)。
popstate事件:当活动历史记录条目更改时,将触发popstate事件。如果被激活的历史记录条目是通过对history.pushState()的调用创建的,或者受到对history.replaceState()的调用的影响,popstate事件的state属性包含历史条目的状态对象的副本。
编程式导航
- 编程式导航 -> 浏览器路由变化:直接调用H5 api,history.pushState()等方法改变浏览器路由
- 编程式导航 -> 程序页面 / 组件更新:history.pushState()方法无法触发popstate事件,所以需要手动触发popstate事件,进而程序根据路由找到组件,页面更新。
history.pushState()或history.replaceState()不会触发popstate事件。只有在做出浏览器动作时,才会触发该事件,如用户点击浏览器的回退按钮(或者在Javascript代码中调用history.back()或者history.forward()方法)
元素事件
- 元素事件 -> 浏览器路由变化:自定义点击事件,内部使用编程式导航的history.pushState()等方法变化路由
- 元素事件 -> 程序页面 / 组件更新:history.pushState()方法无法触发popstate事件,所以需要手动触发popstate事件,进而程序根据路由找到组件,页面更新。
2.案例
如下是元素事件方式切换路由的案例
<a onclick="go(/home)">首页</a>
<a onclick="go(/about)">关于</a>
<div id="html"></div>
<script >
// 元素事件 -> 浏览器路由变化
function go(pathname) {
history.pushState({},null,pathname)
html.innerHTML = pathname;
}
// 元素事件 -> 程序页面 / 组件更新
window.addEventListener('popstate',()=>{
go(location.pathname);
})
</script>
在文章结束前,留下几个可以联系思考的点:
- 多页面应用、单页面应用与前端路由的联系
- 后端路由与前端路由的对比思考
- 对比于上述示例,联系思考一下vue-router在hash模式和history模式下,应该如何实现router-link组件和router-view组件,以及编程式导航router.push等方法该如何实现