【面试题】hash 与 history 路由的实现原理
bug收集:专门解决与收集bug的网站
网址:www.bugshouji.com
今日分享: 【面试题】hash 与 history 路由的实现原理
实现路由的方式:hash模式 和 history模式 两种方式,不论是 angular、vue 还是 React都是这样实现的。
hash 路由:
哈希路由把路由的路径用 # 拼接在 url 后面,当井号 # 后面的路径发生变化时,浏览器并不会重新发起请求,而是会触发 onhashchange 事件。
hash有三个特点:
1. hash 可以改变 url ,但是不会刷新页面, 这并不算是一次 http 请求,所以这种模式不利于 SEO 优化
2. hash 通过 window.onhashchange 的方式,来监听 hash 的改变,借此实现无刷新跳转的功能
3. hash 永远不会提交到 server 端(可以理解为只在前端自生自灭)
底层实现原理
React 中基于hash 的 hashRouter, 监听hanshchange事件获取当前的路径
代码如下:
<body>
<a href="#/a">跳转到/a</a>
<a href="#/b">跳转到/b</a>
<div id="root"></div>
</body>
<script>
let container = document.getElementById('root');
window.addEventListener('hashchange', event => {
console.log(event)
// container.innerHTML = event.newURL
container.innerHTML = `当前的路由为${window.location.hash.slice(1)}`
})
</script>
解析:
hash即URL中“#”字符后面的部分。使用浏览器访问网页时,如果网页URL中带有hash,页面就会定位到id(或name)与hash值一样的元素的位置,故而又称之为锚点。hash还有另一个特点,它的改变不会导致页面重新加载,因此在单页应用流行的当下,它的用处就更多了。通过window.location.hash属性获取和设置hash值。
hashchange事件,顾名思义,就是hash改变时触发的事件。
window.location.hash值的变化会直接反应到浏览器地址栏(#后面的部分会发生变化),同时,浏览器地址栏hash值的变化也会触发window.location.hash值的变化,从而触发onhashchange事件。
history路由:
1. 更新页面而不发送 http 请求
2. 使用 history 模式时,需要通过服务端来允许地址可访问
3. 新的 url 可以是与当前 url 同源的任意 url ,也可以是与当前 url 一样的地址
4. 通过 history.state ,添加任意类型的数据到记录中。
5. 通过 pushState 、 replaceState 来实现无刷新跳转的功能。
底层实现原理
React 中基于history 实现的BrowserRouter, 通过 onpopstate事件和自定义的 onpushstate事件实现
代码:
<body>
<div id="root" style="border:3px solid red;height:200px"> </div>
<button onclick="push('/a')">/a</button>
<button onclick="push('/b')">/b</button>
<button onclick="push('/c')">/c</button>
<script>
let container = document.getElementById('root');
//监听弹出状态的事件 浏览器上的后退按钮
window.onpopstate = function (event) {
//console.log(event);
container.innerHTML = event.state.to;
}
// 自定义实现压栈状态的事件,这个事件window上是没有的
function push(to) {
// 参数一 状态
// 参数二 标题 没有用到
// 参数三 跳转的路径
window.history.pushState({to},null,to)
}
// 覆写window.history.pushState方法
// 1.先保存一下原有的方法
const pushState = window.history.pushState;
// 2.覆写
window.history.pushState = function(state,title,url){
// 3.调用系统的该方法
pushState.call(window.history,state,title,url);
// 4.调用自定义的onpushstate事件
window.onpushstate(state,title,url)
}
// 5.将事件定义在window属性上 浏览器的前进按钮
window.onpushstate = function(state,title,url) {
container.innerHTML = state.to || url
}
</script>
</body>
解析:
1、popstate用来做什么的?
简而言之就是HTML5新增的用来控制浏览器历史记录的api。
2、过去如何操纵浏览器历史记录?
window.history对象,该对象上包含有length和state的两个值,在它的__proto__上继承有back、forward、go等几个功能函数
在popstate之前,我们可以利用back、forward、go对history进行后退和前进操作。
例如:
history.back(); (后退一步,使用history.go(-1)也可实现后退效果)
弊端:只能操作前进后退,但是无法控制前进后要去哪,history.length都只会维持原来的状态
3、popstate的怎么用?
HTML5的新API扩展了window.history,使历史记录点更加开放了。可以存储当前历史记录点pushState、替换当前历史记录点replaceState、监听历史记录点popstate。
pushState、replaceState两者用法差不多。
使用方法:
history.pushState(data,title,url);
//其中第一个参数data是给state的值;第二个参数title为页面的标题,但当前所有浏览器都忽略这个参数,传个空字符串就好;第三个参数url是你想要去的链接;
replaceState用法类似,例如:history.replaceState("首页","",location.href+ "#news");
两者区别:pushState会改变history.length,而replaceState不改变history.length
苟有恒 , 何必三更眠五更起
相关文章
- 苹果MacOS_虚拟机安装详细过程
- 21条最佳实践,全面保障 GitHub 使用安全
- 字节后端实习一面凉经
- 面向接口编程的好处-介绍API数据接口的好处!
- C语言大学生考试全面题库
- 数据治理很抽象吗
- Elasticsearch互联网主流分布式全文检索框架实战-ElasticStack(上)v7.14.0
- 分布式全局ID生成器原理剖析及非常齐全开源方案应用示例
- ElasticJob分布式任务调度应用v2.5.2
- 云原生概念你了解多少
- 主流微服务一站式解决方案Spring Cloud Alibaba入门看这篇就足够了-开篇v2.2.1.RELEASE
- Pulsar云原生分布式消息和流平台v2.8.0
- 回顾2022,展望2023,一个普通98年程序员的自述和分享
- SpringBoot+Mybatis-plus整合easyExcel批量导入Excel到数据库+导出Excel
- Springboot整合策略模式概念->使用场景->优缺点->企业级实战
- 三台服务器使用docker搭建redis一主二从三哨兵,概念-搭建-整合springboot
- IDEA中给源码添加自己注释——private-notes插件安装使用
- docker搭建Elasticsearch、Kibana、Logstash 同步mysql数据到ES
- Spark简单介绍,Windows下安装Scala+Hadoop+Spark运行环境,集成到IDEA中
- SpringBoot自定义注解+异步+观察者模式实现业务日志保存