如果popstate事件来自HTML5 pushstate的后退或前进操作,如何检索?

时间:2012-01-23 23:46:24

标签: javascript html5 browser-history pushstate

我正在开发一个网页,根据我执行相应动画的下一步或后退动作,使用pushstate时会出现问题。当我收到活动时,如何知道用户是否使用Pushstate API点击了后退或转发历史记录按钮?或者我是否必须自己实施某些内容?

2 个答案:

答案 0 :(得分:54)

你必须自己实施,这很容易。

  • 调用pushState时,为数据对象提供唯一的递增ID(uid)。
  • 调用onpopstate处理程序时;检查状态uid是否包含一个包含最后一个状态uid的持久变量。
  • 使用当前状态uid更新持久变量。
  • 根据状态uid是否大于或小于上一个状态uid,执行不同的操作。

答案 1 :(得分:3)

这个答案适用于单页推送状态应用, 或多页应用程序,或两者的组合。 (已更正以修复Mesqualito评论中解决的History.length错误。)

如何运作

我们可以轻松地收听历史堆栈的新条目。 我们知道,对于每个新条目,specification都要求浏览器:

  1. “删除当前条目后的浏览上下文会话历史记录中的所有条目”
  2. “在最后添加新条目”
  3. 因此,在进入的那一刻:

      

    新的进入位置=最后显示的位置+ 1

    解决方案是:

    1. 使用自己在堆栈中的位置标记每个历史记录条目
    2. 在最后显示的位置的会话存储中跟踪
    3. 通过比较两个
    4. 来发现旅行方向

      示例代码

      function reorient() // After travelling in the history stack
      {
          const positionLastShown = Number( // If none, then zero
            sessionStorage.getItem( 'positionLastShown' ));
          let position = history.state; // Absolute position in stack
          if( position === null ) // Meaning a new entry on the stack
          {
              position = positionLastShown + 1; // Top of stack
      
              // (1) Stamp the entry with its own position in the stack
              history.replaceState( position, /*no title*/'' );
          }
      
          // (2) Keep track of the last position shown
          sessionStorage.setItem( 'positionLastShown', String(position) );
      
          // (3) Discover the direction of travel by comparing the two
          const direction = Math.sign( position - positionLastShown );
          console.log( 'Travel direction is ' + direction );
            // One of backward (-1), reload (0) or forward (1)
      }
      
      addEventListener( 'pageshow', reorient );
      addEventListener( 'popstate', reorient ); // Travel in same page

      另请参阅代码的live copy

      限制

      此解决方案忽略外部页面的历史记录条目, 对应用程序来说很陌生,好像用户从未访问过它们。 它仅计算与最后显示的应用程序页面相关的行进方向, 无论在两者之间访问任何外部页面。 如果您希望用户将外部条目推送到堆栈中 (参见Atomosk的评论),那么你可能需要一个解决方法。