如何使用浏览器历史记录api在返回时调用函数单击前进按钮?

时间:2014-07-25 18:49:11

标签: javascript browser-history history.js

假设我有一个页面:http://www.example.com/foo.htm

我想放置一个按钮,显示页面的一部分并隐藏另一部分,例如:

HTML -

<p class="stepOne">Hi, I'm step one. <a id="doit" href="#">Go to Step 2</a></p>
<p class="stepTwo">And I'm step two</p>

JS -

$('#doit').on('click', function(){
    $('.stepOne').hide();
    $('.stepTwo').show();
});

我的问题是: 在用户单击“转到步骤2”链接后,如何在用户单击浏览器的后退按钮时使用HTML历史记录api隐藏第二步并显示第一步?

2 个答案:

答案 0 :(得分:0)

让我们将浏览器的历史视为一个堆栈。每次单击链接或向前导航时,都会将项目推送到堆栈中。无论何时你想要倒退,浏览器都会弹出&#34;一个项目离开堆栈。让我们将这些项目中的每一个称为“状态”#34;浏览器保存有关每个州的一些信息,例如URL,标题和状态对象&#34;如果需要的话。总而言之,当你前进时,新状态会被推到堆栈中,当你想要倒退时,最新状态会从最后状态弹出。

考虑到这一点,你想要完成的是手动将状态推入堆栈。通过这种方式,用户实际上无法在任何地方导航 - HTML5 History API使我们能够在不更改页面的情况下推送/弹出/替换浏览器历史堆栈中的状态。

click事件监听器中,您需要添加一些代码以向历史堆栈添加新状态。类似于:window.history.pushState({}, 'Step 2', '/step-2');

这会向历史记录堆栈添加新状态,您的网址将更改为/step-2。现在,当您单击后退按钮时,它将pop从堆栈状态退出并返回到先前的状态。两个状态都是相同的页面和DOM。

现在,当用户在浏览器中导航back时,您必须考虑更改页面上这两个项目的可见性。这可以通过每次状态更改时在popstate上触发的window事件来检测。看看this plunkr example我放在一起。在click事件侦听器中,DOM被更改(隐藏并显示项目),并且新的历史状态被推入堆栈,其中一个整数表示应该在该历史状态中显示哪个步骤。然后,在popstate事件上,用户向后导航,在事件对象中,我们将获得正在弹出的状态。我们知道我们应该倒退,所以如果弹出的步骤是第2步,我们将要显示第1步。

我对html进行了一些小改动,以便能够简洁地编写代码,并且这里有很多模块化空间 - 无需在javascript中对步骤编号进行硬编码。

这有意义吗?

答案 1 :(得分:0)

以下代码可以解决您在问题中提出的问题。使用Using MySQL UNIQUE Index To Prevent Duplicates,我们可以像这样扩展您的示例代码(注释描述了已添加到您的代码中的三个部分A,B,C)

// Part A: For the initial "step 1" we create a history state object
var historyStateObjectStep1 = {"step":"one"};
// which we tell the browser to use to represent the current state/step in
// history. Since the browser had an idea about the "now"-state in history 
// already, which is now "replaced" this is done via history.replaceState
history.replaceState(historyStateObjectStep1,"");

// Part B: To react to history events like back-/forward-button pressed, 
// we have to setup an EventListener for the "history"-popstate event. 
window.addEventListener("popstate",function(event){
      // the history state objects we have setup via replaceState/pushState
      // before are provided via the event objects property event.state
      var historyStateObject = event.state;

      // if state object is "object" and as setup has an attribute "step" 
      // with value "one"
      if(typeof historyStateObject == "object" 
         && historyStateObject.step === "one" )
      {
          // then it means that the user used the browsers "back" button 
          // and since we are now at history state "stepOne" we show it
          $('.stepOne').show();
          // and hide stepTwo
          $('.stepTwo').hide();
      } 
      // in else case that the historyStateObject is an object and has an
      // attribute step set to the value "two" then...
      else if(typeof historyStateObject == "object" 
         && historyStateObject.step === "two" )
      {
          //...the user has used the browser buttons (forward/back) to reach
          // the state "stepTwo", hence we show it and 
          $('.stepTwo').show();
          // hide stepOne
          $('.stepOne').hide();
      }
},false);


$('#doit').on('click', function(){
    // PART C: Upon clicking the "doit"-button (to go to step two), we 
    // create an history state object for step 2 
    var historyStateObjectStep2 = {"step":"two"};

    // which we then insert intto the browser history, or in other words 
    // "push" the newly created historyStateObejectStep2 to the history, via
    // the function history.pushState
    history.pushState(historyStateObjectStep2,"");


    $('.stepOne').hide();
    $('.stepTwo').show();
});