Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/458.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何检索popstate事件是否来自HTML5 pushstate的后退或前进操作?_Javascript_Html_Browser History_Pushstate - Fatal编程技术网

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

Javascript 如何检索popstate事件是否来自HTML5 pushstate的后退或前进操作?,javascript,html,browser-history,pushstate,Javascript,Html,Browser History,Pushstate,我正在开发一个网页,根据下一步或下一步的动作,我会制作相应的动画,使用pushstate时会出现问题。当我收到事件时,我如何知道用户是否使用Pushstate API单击了“后退”或“前进”历史按钮?或者我是否必须自己实现某些功能 您必须自己实现它,这很容易 调用pushState时,为数据对象指定唯一的递增id(uid) 调用onpopstate处理程序时;对照包含最后一个状态uid的持久变量检查状态uid 使用当前状态uid更新持久变量 根据状态uid大于还是小于上一个状态uid,执行不同

我正在开发一个网页,根据下一步或下一步的动作,我会制作相应的动画,使用pushstate时会出现问题。当我收到事件时,我如何知道用户是否使用Pushstate API单击了“后退”或“前进”历史按钮?或者我是否必须自己实现某些功能

您必须自己实现它,这很容易

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

此答案应适用于单页推送状态应用程序, 或多页应用程序,或两者的组合。 (修正了Mesqualito评论中提到的
历史.长度
错误。)

工作原理 我们可以轻松地侦听历史堆栈中的新条目。 我们知道,对于每个新条目,都需要浏览器:

  • “删除当前条目之后浏览上下文会话历史记录中的所有条目”
  • “在末尾追加一个新条目”
  • 因此,在进入时:

    新输入位置=上次显示的位置+1

    因此,解决办法是:

  • 在每个历史记录条目的堆栈中标记其自己的位置
  • 在上次显示的位置的会话存储中保持跟踪
  • 通过比较两者来发现旅行的方向
  • 示例代码 另请参见代码的一部分

    限度 此解决方案忽略外部页面的历史记录条目, 与应用程序无关,好像用户从未访问过它们。 它仅根据最后显示的应用程序页面计算行驶方向, 不管其间访问了什么外部页面。 如果希望用户将外来项推送到堆栈上
    (请参阅Atomosk的评论),然后您可能需要一个解决方法。

    popstate事件会显示“请更改为此状态”。它似乎假设您知道当前处于何种状态,因此需要执行哪些操作来更改状态。问题是历史是一个堆栈,因此如果我有一个列表,我向前、向前、向前、向后、向前、向前,列表是:[1,2,3,4,5],那么历史将是:[1,2,3,4,3,4]。在数字上是很容易的,但是在url上要知道哪个url是下一个,哪个是上一个并不是那么容易。下面bennedich的评论对我帮助很大。接受它可能会更好,这样它也能更有效地帮助他人。当页面/视图层次结构定义清楚时,这种方法效果很好,而且某个页面总是在另一个页面之后出现。当导航更加动态时,您不能依赖递增的UID。我已经通过使用sessionStorage来维护最后X页的堆栈来解决这个问题。然后,在popstate事件中,您可以从sessionStorage检查堆栈,以查看新页面URL是否与N-2页面的URL相同。使用sessionStorage而不是普通变量,因此这会在页面边界之间持久化。@frontendbeauty我认为您应该使用代码段发布您的建议作为答案。此外,不要检查值是否大于/小于,您可以编写一个状态更改管理器,检查id以查看当前状态是什么以及它将移动到什么状态,然后执行相应的动画如果这么简单,为什么不编写实现?对于任何可能的用例,我都看不出如何使其无bug。不管我在哪里保持当前状态,我都能找出如何滥用它。@如果你在页面上,你在中间页面B,你的堆栈看起来像这个代码[a,b,a]:<代码>你得到<代码> POPSTATE < /Cube >事件,你怎么知道它是返回还是前进?在你的站点上做一些导航,打开一个外部链接,按浏览器后退按钮两次,长按浏览器前进按钮并选择外部站点会话存储,然后按后退。也许我太过分了:)。另外,我认为您的函数可以替换为
    const direction=Math.sign(history.length-(sessionStorage.getItem('statelastshighed')| | 0));sessionStorage.setItem('stateLastShowed',history.length)因为您总是将
    历史记录.length
    置于历史记录状态。@Atomosk(1)您是对的,外部链接处理不正确。我加了一个警告。(2) 我认为你删减的代码会失败。仅确定堆栈中新条目的位置。您还需要代码来处理另一个案例,这是一个重新访问的条目。是的,您是对的。我永远不会习惯前端API是多么糟糕。用后退/前进按钮检查我能走多远应该是一行,但有人决定不这样做。浏览器后退/前进历史有一个固定的限制,在Chrome 50中。当您达到该限制时,
    history.length
    将始终产生相同的数字(在我的情况下为50),因此此解决方案始终返回0作为方向,因为所有状态项都具有相同的位置。@Mesqalito您是对的,浏览器对
    history.length的限制使其不可靠。我将答案改为使用会话变量
    positionlastshighed
    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) and forward (1)
    }
    
    addEventListener( 'pageshow', reorient );
    addEventListener( 'popstate', reorient ); // Travel in same page