当前位置:首页 > 数据库

利用pushState, popState和location.hash等方法自己实现一个小型路由

这篇文章主要是利用路由记录下HTML5中history提供的pushState, replaceStateAPI。***通过这些API自己实现小型的等方路由。

关于window.history提供的法自API请参见Mozilla文档

其中history提供的pushState和replaceState2个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去请求数据。页面体验更加流畅; 可以利用本地缓存,优化页面体验。在不同页面切换的过程中更加流畅; 可进行按需加载...

等等一些实用的好处吧。

分享到:

滇ICP备2023006006号-16