当前位置: 首页 > Web前端 > HTML

单页应用中如何优雅的监听url的变化

时间:2023-04-03 00:06:42 HTML

单页应用的原理是从早期根据url的hash变化到H5的历史变化来实现页面重渲染而不刷新。那么如何在单页应用中监控URL变化呢?本文将总结如何优雅地监控单页应用程序中的URL变化。单页应用原理监听url中的hash变化通过historyreplaceState和pushState行为监听监听改变url的事件原文在我的博客:https://github.com/forthealll...欢迎光临star1.单页应用原理单页应用的原理在我们上一篇React-Router源码阅读的文章中有详细讲解。这里简单介绍一下。单页应用允许页面重新渲染而不刷新,可以通过html5Bom对象中的hash或history更改url,但页面不刷新。(1)通过hash实现单页面路由早期的前端路由是通过hash实现的:改变url的hash值不会刷新页面。所以可以通过hash实现前端路由,达到不刷新的效果。散列属性位于位置对象中。在当前页面,可以通过:window.location.hash='edit'来改变当前url的hash值。执行完上面的哈希赋值后,页面的url发生了变化。赋值前:http://localhost:3000赋值后:http://localhost:3000/#editurl中多了一个以#结尾的hash值,但是页面的hash值在赋值前后发生了变化,导致页面的完整url发生变化,但是页面没有刷新。另外,除了通过window.location.hash改变当前页面的hash值外,还可以通过html的a标签实现:edit(2)通过historyRoutingHTML5的History接口实现前端,History对象是低级接口,不继承任何接口。History接口允许我们操作浏览器会话历史记录。历史提供了一些属性和方法。History的属性:History.length:返回会话历史中有多少条记录,包括当前会话页面。另外,如果你打开一个新的Tab,这个长度的值为1到浏览器会话历史中的下一页,与浏览器的前进按钮History相同。go():可以跳转到浏览器会话历史中的指定记录页面。History.pushState():pushState可以将给定的数据推送到浏览器会话历史栈中。此方法接收3个参数,对象、标题和一串url。pushState后,当前页面url会发生变化,但不会刷新。History.replaceState():replaceState会将当前session页面的url替换成指定的数据。replaceState后,当前页面的url也会改变,但不会刷新页面。上述方法中,pushState和repalce的相同点是:都会改变当前页面显示的url,但都不会刷新页面。不同点:pushState被压入浏览器的sessionhistory栈,会把History.length加1,replaceState替换当前sessionhistory,所以不会增加History.length。(3)总结??通过改变hash值,或者history的repalceState和pushState可以改变url不刷新。这样一来,还有一个问题需要解决:‖‖如何监听url的变化‖‖因为我们不仅要在不刷新的情况下改变url,还要监听这个url改变的行为,并根据需要重新渲染view对这种行为。在接下来的几章中,我们将重点介绍如何监控URL的变化。2.监听url中的hash变化,如果url被hash改变了,就会触发hashchange事件。只要监听hashchange事件,就可以捕捉到通过hash改变url的行为。window.onhashchange=function(event){console.log(event);}//或window.addEventListener('hashchange',function(event){console.log(event);})当hash值发生变化时,输出一个哈希更改事件。HashChangeEvent的具体取值是:{isTrusted:true,oldURL:"http://localhost:3000/",newURL:"http://localhost:3000/#teg",type:"hashchange"........}有了监听事件,在不刷新的情况下改变hash页面,我们就可以在监听事件的回调函数中实现显示和隐藏不同UI显示的功能,从而实现前端路由。3、通过history监听改变url的事件上一章我们提到通过History改变url有几种方式:History.back(),History.forward(),History.go(),History.pushState()和历史。替换状态()。同时历史中还支持一个事件,就是popstate。第一个想法是,如果popstate可以监控所有由history方法引起的url变化,那么你就完了。不幸的是:History.back()、History.forward()、History.go()事件会触发popstate事件,但是History.pushState()和History.replaceState()不会触发popstate事件。如果是History.back(),History.forward(),History.go()那么就会触发popstate事件,我们只需要:window.addEventListener('popstate',function(event){console.log(event);})可以监听对应的行为,手动调用:window.history.go();window.history.back();window.history.forward();会触发这个事件。另外,点击后退和前进按钮也会触发popstate事件。这个事件的内容是:PopStateEvent{isTrusted:true,state:null,type:"popstate",target:Window,currentTarget:Window,…}但是,History.pushState()和History.replaceState()不会触发popstate事件,例如:window.addEventListener('popstate',function(event){console.log(event);})window.history.pushState({first:'first'},"page2","/first"})上面的例子不会有输出,因为没有监听popstate事件。但是,虽然History.go和History.back()可以触发popstate事件,但它们会刷新页面。我们在单页应用中使用了replaceState和pushState,所以还有一个问题等待解决:如何监控replaceState和pushState行为4.replaceState和pushState行为的监控在上面的例子中,我们发现History.replaceState和pushState不触发popstate事件,那么如何监控这两个行为。你可以在方法中主动触发popState事件。另一种是在方法中创建一个新的全局事件。具体方法是:var_wr=function(type){varorig=history[type];returnfunction(){varrv=orig.apply(this,arguments);vare=新事件(类型);e.arguments=参数;window.dispatchEvent(e);返回房车;};};history.pushState=_wr('pushState');history.replaceState=_wr('replaceState');这样就新建了两个事件,事件名称为pushState和replaceState,我们可以全局监听:window.addEventListener('replaceState',function(e){console.log('THEYDIDITAGAIN!replaceState111111');});window.addEventListener('pushState',function(e){console.log('他们又做了一次!pushState2222222');});这样就可以监控pushState和replaceState的行为。参考文章:https://stackoverflow.com/que...