利用pushState, popState和location.hash等方法自己实现一个小型路由
来源:互联网 发布:dictionary软件下载 编辑:程序博客网 时间:2024/05/17 20:38
这篇文章主要是记录下HTML5中history提供的pushState
, replaceState
API。最后通过这些API自己实现小型的路由。
关于window.history提供的API请参见Mozilla文档
其中history
提供的pushState
和replaceState
2个API提供了操作浏览器历史栈的方法。
其中pushState
:
history.pushState(data, null, '#/page=1'); pushState接收3个参数,第一个参数为一个obj,表示浏览器 第二个参数是document.title的值,一般设定为`null` 第三个参数string,用以改变 当前url
pushState
方法在改变url
的同时向浏览器历史栈中压入新的历史记录。
接收url
的参数为string
类型,用以改变当前地址栏的url.需要注意的一点就是这个参数不能和跨域,即协议,域名,端口必须都是相同的,如果出现跨域的情况,即会提示:
Uncaught DOMException: Failed to execute 'pushState' on 'History': A history state object with URL 'http://www.baidu.com/' cannot be created in a document with origin 'http://commanderXL.com' and URL
Example:
打开www.baidu.com history.pushState(null, null, '?page=1') //地址栏变成 www.baidu.com/?page=1 history.pushState(null, null, '#page=2'); //地址栏变成 www.baidu.com/#page=2
其中replaceState
:
history.replaceState(null, null, '#page=2');
replaceState
接收的参数pushState
相同,但是最终的效果是:地址栏url会根据接收的参数而变化,但是浏览器并未在当浏览历史栈中增加浏览器的历史记录,而是替换当前的浏览器历史记录。
通过pushState
和replaceState
虽然能改变URL,但是不会主动触发浏览器reload
。
window
对象还提供popstate
方法:
window.addEventListener('popstate', function() { });
这个方法用以监听浏览器在不同历史记录中进行切换,而触发相应的事件。
在浏览器提供的history对象上还有go
, back
方法,用以模拟用户点击浏览器的前进后退按钮。在某个web应用当中,比如点击了<a>
标签,发生了页面的跳转。这时调用history.back()
;方法后页面回退,同时页面发生刷新,这时window.onpopstate
无法监听这个事件。但是如果是通过pushState
或者replaceState
来改变URL且不发生浏览器刷新的话,再使用history.back()
或history.go()
,这样popstate
事件会被触发。
history.pushState({page: 1}, null, '?page=1'); history.pushState({page: 2}, null, '?page=2'); history.back(); //浏览器后退 window.addEventListener('popstate', function(e) { //在popstate事件触发后,事件对象event保存了当前浏览器历史记录的状态. //e.state保存了pushState添加的state的引用 console.log(e.state); //输出 {page: 1} });
PS: 通过pushState
在url上添加?page=1
可以通过location.search
去获取search
的内容。不过如果通过location.search
去改变url
的话是会主动触发浏览器reload
的。这个特性可以和下面将的关于hash
的内容对比下。
API大致了解了,那么这些方法可以运用到哪些地方呢?一个比较常用的场景是就在单页应用中,通过这些API完成前端的路由设计,利用pushState
,replaceState
可以改变url
同时浏览器不刷新,并且通过popstate
监听浏览器历史记录的方式,完成一系列的异步动作。
<a data-href="/post"></a> <a data-href="/login"></a> //路由 const Router = []; const addRoute = (path = '', handle = () => {}) => { let obj = { path, handle } Router.push(obj); } //添加路由定义 addRoute('/post', function() { //do something }); addRoute('/login', function() { //do something }) //路由处理 const routeHandle = (path) => { Router.forEach((item, index) => { if(item.path === path) { item.handle.apply(null, [path]); return true; } }) return false; } //拦截默认的a标签行为 document.addEventListener('click', function(e) { let dataset = e.target.dataset; if(dataset) { if(routeHandle(dataset.href)) { //阻止默认行为 e.preventDefault(); } } })
大致的实现思路就是,通过<a>
添加路由信息,然后拦截<a>
标签的默认行为,并与注册的路由信息进行匹配。若匹配成功调用对应的handle
方法.
不过pushState
和replaceState
方法在低版本的IE浏览器下兼容性不是很好。所以可以进行降级使用hash
来进行路由设计。
hash
?请戳我。
可以通过location.hash
获取url
上第一个#(fragment)
及后面的内容。同时还能通过location.hash
改写其内容,且不会主动触发浏览器reload
。 有些功能是不是和pushState
和replaceState
一样? 所以为了兼容到低版本的浏览器,可以通过监听#
变化来进行路由设计。
那么如何去监听呢? 比较粗暴的一种方式就是polling
。
var oldHash = location.hash; setTimeInterval(function() { if(oldHash !== location.hash) { //do something oldHash = location.hash; } }, 100);
不过,H5还提供了一个API: hashchange
。它的就可以直接代替上面的polling
方法,来监听#
的变化。
window.addEventListener('hashchange', function() { routeHandle(locaiton.hash); });
这个小型的路由设计可以参见我的github.
稍微总结下:
上面主要介绍了history提供的一些API,hash的相关知识。在平时可以运用到SPA当中,Gmail就是通过hash来进行路由设计的。它相对于页面跳转来说:
页面只需要加载一次。后面的页面切换可以通过ajax去请求数据。页面体验更加流畅;
可以利用本地缓存,优化页面体验。在不同页面切换的过程中更加流畅;
可进行按需加载...
- 利用pushState, popState和location.hash等方法自己实现一个小型路由
- 利用history.pushState实现前端路由
- 使用history.pushState()和popstate事件实现AJAX的前进、后退功能
- H5,API的pushState(),replaceState()和popstate()作用,用法
- 利用iframe和location.hash实现跨域
- h5 pushState replaceState popState 总结
- html5新特性:利用history的pushState等方法来解决使用ajax导致页面后退和前进的问题
- 利用HASH写的一个简单路由
- pushState()、popstate事件配合ajax实现浏览器前进后退页面局部刷新
- 利用php和mysql实现小型聊天室
- 利用location.hash实现跨域iframe自适应高宽
- 一个简单的例子看明白如何利用window.location.hash实现ajax操作时浏览器的前进/后退功能
- 一个简单的例子看明白如何利用window.location.hash实现ajax操作时浏览器的前进/后退功能
- 利用jsonp、iframe和location.hash解决跨域问题
- history.pushState()实现不跳转,改变路由异步刷新
- window.location.hash常用方法
- 实现一个小型通讯录
- history.pushState() 和 history.replaceState() 方法
- PHP Call to undefined function mysql_connect()
- 2017.1.21【初中部 GDKOI】模拟赛B组
- C++的tie()函数
- Tango 开发指南 — 参考帧
- 3D游戏开发之在UE4中创建非玩家角色(NPC)
- 利用pushState, popState和location.hash等方法自己实现一个小型路由
- 浅析Spring的JdbcTemplate
- 多读书少睡觉
- 软件开发知识体系
- RxJava学习经验谈——lift操作
- Android SVG矢量资源的使用方法
- 编程珠玑: 15.1实现一个哈希表统计字符串出现次数 -------解题总结
- android开发万能圆角ImageView
- js命令模式的案例——键盘按下及事件回放