使用HTML5历史记录的后退按钮只能使用一次

时间:2018-03-31 03:23:59

标签: javascript nginx back-button browser-history html5-history

我正在尝试为单页面应用中的后退按钮构建一个简单的仅限javascript的HTML5实现。

作为第一步,我有一个骨架原型可以工作,但只有一次 - 当我走1> 2> 3然后从3按回来时,它回到2好,但仍然卡在那里2无论如何我按下后退按钮多少倍。行为总是相同的,并且跨浏览器,所以我确信它必须是我的逻辑,但即使经过多次尝试,我也无法弄清楚它是什么。此外,前进按钮似乎也被停用。

为了简单解释一下,我有三个(隐藏的)div,每个都有一个(可见的)'描述',点击它打开实际的div。页面加载时,只有描述可见,没有内容。当用户点击任何一个div的描述时,该div显示,其余的/保持隐藏状态。

该网站位于nginx服务器后面,该服务器通过以下指令将所有内容传递到主页:

location /div1{
        proxy_pass https://192.168.43.220:8765/;
    }

由于它相对简单,并且可以直接复制粘贴复制,我可以自由地将它粘贴在这里。已经存在计数器变量和许多console.logs,因此应该让尝试修复它的人更容易。

我也很感激为什么这不起作用的任何解释。

<html>
<head>
</head>
<body>
    <b href="#div1" onclick=show_div1()>DIV1</b>
    <b href="#div2" onclick=show_div2()>DIV2</b>
    <b href="#div3" onclick=show_div3()>DIV3</b>

    <div id="div1">
        <p>This is div number 1</p>
    </div>
    <div id="div2">
        <p>This is div number 2</p>
    </div>
    <div id="div3">
        <p>This is div number 3</p>
    </div>
</body>

<script>
    document.addEventListener("DOMContentLoaded", function(event){
        on_page_load();
    });
    function on_page_load(){
        document.getElementById("div1").style.display="none";
        document.getElementById("div2").style.display="none";
        document.getElementById("div3").style.display="none";
        var p = window.location.pathname.split("/")[1];
        console.log("on page load, pathname: " + p);
        history.pushState({url: p}, null, p);
        console.log("js routing to: " + p);
        js_route(p);
        n1 = 0; n2 = 0; n3 = 0;
    }
    function show_div1(){
        document.getElementById("div1").style.display="block";
        document.getElementById("div2").style.display="none";
        document.getElementById("div3").style.display="none";
        n1 = n1 + 1;
        console.log("showing div1 for " + n1 + "th time");
        history.pushState({url: 'div1', n: n1}, null, "div1");
    }
    function show_div2(){
        document.getElementById("div2").style.display="block";
        document.getElementById("div1").style.display="none";
        document.getElementById("div3").style.display="none";
        n2 = n2 + 1;
        console.log("showing div2 for " + n2 + "th time");
        history.pushState({url: 'div2', n: n2}, null, "div2");
    }
    function show_div3(){
        document.getElementById("div3").style.display="block";
        document.getElementById("div2").style.display="none";
        document.getElementById("div1").style.display="none";
        n3 = n3 + 1;
        console.log("showing div3 for " + n3 + "th time");
        history.pushState({url: 'div3', n: n3}, null, "div3");
    }

    window.onpopstate = function(event) {
        var popped_url = event.state.url;
        var popped_n = event.state.n;
        console.log("popstate url: " + popped_url);
        console.log("onpopstate, routing to: " + window.location.pathname + " and n is " + popped_n);
        js_route(popped_url);
        //js_route(window.location.pathname.split("/")[1]);
    }

    function js_route(path){
        switch(path){
            case "div1":
                show_div1();
                break;
            case "div2":
                show_div2();
                break;
            case "div3":
                show_div3();
        }
    }
</script>

1 个答案:

答案 0 :(得分:0)

好的,经过多轮调试和思考后,我发现了什么被打破了。

show_div函数将状态全部推送到历史记录中。因此,当popstate事件处理程序调用{​​{1}}函数时,它会调用正确的历史记录,但随后会将该状态推回到历史记录中。因此,当从1> 2> 3,然后从3返回时,它变为2,但也将2再次推入历史 - 所以再次返回将弹出历史中的最新状态,现在是2.因此创建了无限循环任何进一步的popstate事件。

解决这个问题的方法是创建一组新的函数 - js_route,它们与show_div_hist函数执行相同的操作,但不会将任何内容推送到历史记录中。同样,新的路由器show_divjs_route_history函数执行相同的操作,但会调用前面提到的js_route函数。

就是这样。很好地工作。

show_div_hist