如何检索 popstate 事件是否来自 HTML5 Pushstate 的后退或前进操作?

问题描述 投票:0回答:2

我正在开发一个网页,根据下一个或后一个操作我执行相应的动画,使用推送状态时会出现问题。当我收到事件时,我如何知道用户是否使用 Pushstate API 单击后退或前进历史记录按钮?或者我是否必须自己实现某些内容?

javascript html browser-history pushstate
2个回答
75
投票

您必须自己实现,这非常简单。

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

13
投票

这个答案应该适用于单页推送状态应用程序, 或多页应用程序,或两者的组合。 (已更正以修复 Mesqualito 评论中提到的

History.length
错误。)

如何运作

我们可以轻松监听历史堆栈中的新条目。 我们知道,对于每个新条目,规范要求浏览器:

  1. “删除浏览上下文的会话历史记录中当前条目之后的所有条目”
  2. “在末尾添加新条目”

在进入的那一刻,因此:

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

那么解决办法是:

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

示例代码

'use strict';

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( 'Position ' + position );
    console.log( 'Travel direction is ' + direction ); }
      // One of backward (-1), reload (0) and forward (1)

addEventListener( 'pageshow', reorient );
addEventListener( 'popstate', reorient ); }()); // Travel in same page

另请参阅代码的 live copy

限制

此解决方案忽略外部页面的历史条目, 对于应用程序来说是陌生的,就好像用户从未访问过它们一样。 它仅计算与最后显示的应用程序页面相关的行进方向, 无论其间访问过任何外部页面。 如果您希望用户将外部条目推入堆栈 (请参阅 Atosk 的评论),那么您可能需要一个解决方法。

© www.soinside.com 2019 - 2024. All rights reserved.