应用pushState, popState和location.hash等要领本身完成一个小型路由

这篇文章主假如记录下HTML5中history供应的pushState, replaceStateAPI。末了经由过程这些API本身完成小型的路由。

关于window.history供应的API请拜见Mozilla文档

个中history供应的pushStatereplaceState2个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会依据吸收的参数而变化,然则阅读器并未在当阅读汗青栈中增添阅读器的汗青记录,而是替代当前的阅读器汗青记录。

经由过程pushStatereplaceState虽然能转变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要领.

不过pushStatereplaceState要领在低版本的IE阅读器下兼容性不是很好。所以能够举行降级运用hash来举行路由设想。

hash请戳我

能够经由过程location.hash猎取url上第一个#(fragment)及背面的内容。同时还能经由过程location.hash改写其内容,且不会主动触发阅读器reload。 有些功用是否是和pushStatereplaceState一样? 所以为了兼容到低版本的阅读器,能够经由过程监听#变化来举行路由设想。

那末怎样去监听呢? 比较粗犷的一种体式格局就是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来举行路由设想的。它相对于页面跳转来讲:

  1. 页面只须要加载一次。背面的页面切换能够经由过程ajax去要求数据。页面体验越发流通;

  2. 能够应用当地缓存,优化页面体验。在差别页面切换的过程当中越发流通;

  3. 可举行按需加载…

等等一些有用的优点吧。

项目地点

项目地点请戳我

    原文作者:苹果小萝卜
    原文地址: https://segmentfault.com/a/1190000007166839
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞