前端路由的实现(三) —— History的pushState和replaceState用法
HTML5中history提供的pushState
, replaceState这两个
API。它们提供了操作浏览器历史栈的方法。
pushState能够在不加载页面的情况下改变浏览器的URL。这个方法接受三个参数:
状态对象,新状态的标题和可选的相对URL。
history.pushState(data, null, '#/page=1');
pushState接收3个参数,第一个参数为一个obj,表示浏览器的state属性;
第二个参数是document.title的值,一般设定为`null`;
第三个参数string,用以改变当前url;
pushState
方法在改变url
的同时向浏览器历史栈中压入新的历史记录。
接收url
的参数为string
类型,用以改变当前地址栏的url.需要注意的一点就是这个参数不能和跨域,即协议,域名,端口必须都是相同的,如果出现跨域的情况,即会提示:
Example:
其中 replaceState:
replaceState
接收的参数pushState
相同,但是最终的效果是:地址栏url会根据接收的参数而变化,但是浏览器并未在当浏览历史栈中增加浏览器的历史记录,而是替换当前的浏览器历史记录。
通过pushState
和replaceState
虽然能改变URL,但是不会主动触发浏览器reload
。
window
对象还提供 popstate
方法 :
这个方法用以监听浏览器在不同历史记录中进行切换,而触发相应的事件。
在浏览器提供的history对象上还有go
, back
方法,用以模拟用户点击浏览器的前进后退按钮。在某个web应用当中,比如点击了<a>
标签,发生了页面的跳转。这时调用history.back()
方法后页面回退,同时页面发生刷新,这时window.onpopstate
无法监听这个事件。但是如果是通过pushState
或者replaceState
来改变URL且不发生浏览器刷新的话,再使用history.back()
或history.go()
,这样popstate
事件会被触发。
输出如下:
注意: 通过pushState
在url上添加?page=1
可以通过location.search
去获取search
的内容。不过如果通过location.search
去改变url
的话是会主动触发浏览器reload
的。
API大致了解了,那么这些方法可以运用到哪些地方呢?一个比较常用的场景是就在单页应用中,通过这些API完成前端的路由设计,利用pushState
, replaceState
可以改变url
同时浏览器不刷新,并且通过 popstate
监听浏览器历史记录的方式,完成一系列的异步动作。
简单的路由如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
a {color: red;text-decoration: underline;}
</style>
</head>
<body>
<a data-href="/post">post</a>
<a data-href="/login">login</a>
<script>
const Router = [];
const addRoute = (path ='', handle=() =>{}) => {
let obj = {
path,
handle
};
Router.push(obj);
}
// 添加路由定义
addRoute('/post', function(){
// todo...
alert('/post');
})
addRoute('/login', function(){
// todo...
alert('login');
})
// 路由处理
const routeHandle = (path) => {
for(var item of Router){
if (item.path === path) {
item.handle.apply(null, [path]);
return true;
}
}
}
document.addEventListener('click', function(e) {
let dataset = e.target.dataset;
if(dataset) {
if(routeHandle(dataset.href)) {
var url = window.location.href;
history.pushState({route: dataset.href}, null, oriUrl + dataset.href);
//阻止默认行为
return false;
// e.preventDefault();
}
}
})
</script>
</body>
</html>
大致的实现思路就是,通过<a>
添加路由信息,然后拦截<a>
标签的默认行为,并与注册的路由信息进行匹配。若匹配成功调用对应的handle
方法。
最新文章
- [Erlang 0124] Erlang Unicode 两三事 - 补遗
- 关于CAP定理的个人理解
- 复习---JS-Array 对象
- [Tool] Fiddle2基本使用
- Laravel timestamps 设置为unix时间戳
- GCC下32位与64位机器类型变量所占字节数
- Canvas标签初探
- Swift的74标准功能
- 如何测试本地是否能够正常访问云服务器的 Web 端口
- Go 数据结构--二分查找树
- js实现文字逐个出现动效
- Python——SMTP发送邮件
- BZOJ4386[POI2015]Wycieczki / Luogu3597[POI2015]WYC - 矩乘
- es 测试代码
- des加密delphi与c#
- ERROR tool.ImportTool: Encountered IOException running import job: java.io.IOException: Hive exited with status 2
- Java编程的逻辑 (42) - 排序二叉树
- clean code(一)
- 在Docker和Kubernetes上运行MongoDB微服务
- python .bat
热门文章
- Luogu P4180 【模板】严格次小生成树[BJWC2010]
- [转]Entity Framework教程(第二版)
- 数论,质因数,gcd——cf1033D 好题!
- PAT甲级——A1005 Spell It Right
- ireport 无法打开问题
- 01_springmvc基础入门
- Django项目: 项目环境搭建 ---- 二、django项目设置
- springmvc-@RequestBody无法映射首字母大写的属性
- MFC安装与部署(程序打包)
- HBase实际应用中的性能优化方法