当我从外部链接导航回来时是否应该触发window.statechange?

时间:2013-10-31 16:39:35

标签: html5 history.js

我正在使用History.js(jquery.history.js v1.8b2)。 Chrome版本30.0.1599.101 m。

我无法弄清楚如何让History.js以我期望的方式工作。

我有一个有两个链接的页面。第一个模拟ajax操作。它只是将页面中<h2>中的文本从“开始”更改为“2”。第二个链接指向google.com。

这就是我的所作所为:

  • 清除Chrome中的缓存
  • 加载页面
  • 点击第一个链接(我调用pushState,发生状态更改,然后我将文本更新为“2”)
  • 点击google.com链接(转到Google)
  • 点击浏览器后退按钮。

单击后退按钮时,我希望应该调用statechange处理程序,然后我将获取状态对象,以便将文本恢复为“2”。

但是没有调用处理程序。所以我的页面留下了文本“start”(浏览器中的缓存页面)。有趣的是,url设置为我在pushState调用中推送的“2”版本。

我错过了什么吗?这是我的代码:

<h2 id="state">start</h2>

<a id="2" class="button" href="#">Goto State 2</a>

<a href="http://google.com">Goto google</a>

<script type="text/javascript">

    $(function() {

        History.Adapter.bind(window, "statechange", function() {
            console.log("statechange called");

            var state = History.getState();

            if (state.data.mystate) {
                // Restore the old state
                $("#state").text(state.data.mystate);
            } else {
                // Start state
                $("#state").text("start");
            }
        });


        $(".button").click(function(e) {
            // push the state we're transitioning to
            var newState = $(this).attr("id");

            History.pushState(
                { mystate: newState },
                "at state " + newState,
                "http://localhost:50494/PushState?state=" + newState);

            // statechange will be called now, and we'll update the page from our newState

            e.preventDefault();
        });


    });

</script>

1 个答案:

答案 0 :(得分:0)

我认为答案是否定的,当从页面外部导航回来时,不应该调用statechange。

我注意到http://browserstate.github.com/history.js/demo/上的演示正如我所期望的那样工作,所以我做了一个视图来源,看看它是如何工作的。据我所知,这是你应该如何使用History.js。

  1. 加载页面时,您会查看History.getState()。data。 如果您认出其中的某个州,那么这意味着您将从其他页面导航回您的页面,例如从您访问的外部链接。 (注意:浏览器可能刚刚从缓存中加载了您的页面,或者它可能已经从服务器重新加载。无论如何,因为您要使用刚刚找到的状态更新页面/ ui)。因此,请将您的页面更新为该状态。 如果您无法识别状态,那么就您的网页而言,这是第一次加载。适当地开始。
  2. 状态更改事件将在页面中“ajax”状态之间的浏览器后退/前进按钮上调用(在此页面中您已按下的状态)。 调用pushState()时也会调用它。嗯,这不是很混乱吗?是的,所以当您想要转换到页面中的新状态时,请遵循以下模式:
  3. 准备你的状态对象(可能涉及ajax调用),
  4. 致电pushState(yourObject,...)
  5. 请勿更新您的网页/ ui。
  6. 你实际上是从statechanged处理程序更新你的页面/ ui,这会立刻被调用。
  7. 我错误地认为你应该做更新页面的所有工作,然后再推送状态。这只会让事情变得困难,因为状态也会被调用。

    此外,通常情况下,您应该在您所在的一个页面中推送类似ajax的转换的状态。不要为你在页面外跟随的链接推送状态(除非你真的了解这一切,并试图做一些奇特的事情)。

    我在这里更新了示例代码,以显示现在对我有用的内容:

    <h2 id="state">start</h2>
    
    <a id="2" class="button" href="#">Goto State 2</a>
    
    <a href="http://google.com">Goto google</a>
    
    
    <script type="text/javascript">
    
        $(function () {
            // page loading, check for available state I recognize
            var availableState = History.getState();
    
            if (!availableState.data.mystate) {
                // loading for the first time
                $("#state").text("start");
            } else {
                // load from the available state
                loadState(availableState);
            }
    
            History.Adapter.bind(window, "statechange", function () {
                var state = History.getState();
                loadState(state);
            });
    
            function loadState(state) {
                if (state.data.mystate) {
                    // update the page to this state
                    $("#state").text(state.data.mystate);
                } else {
                    // update the page to the initial state
                    $("#state").text("start");
                }
            }
    
    
            $(".button").click(function (e) {
                // The user clicked a button, so we want to transition to a new state
                // in this page. Push the state we're transitioning to (which we've hidden
                // in the id attribute in this example).
                var newState = $(this).attr("id");
    
                History.pushState(
                    { mystate: newState },
                    "at state " + newState, // title
                    "?state=" + newState);  // url
    
                // statechange will be called now, and we'll update the page from our newState
    
                e.preventDefault();
            });
    
    
        });
    
    </script>