我正在开发一个网页,根据用户点击的“下一页”或“上一页”来做相应的动画。但是当使用pushstate时会出现问题。当我接收到事件时,如何知道用户是通过Pushstate API点击了后退或前进历史记录按钮呢?还是我需要自己实现一些东西?
我正在开发一个网页,根据用户点击的“下一页”或“上一页”来做相应的动画。但是当使用pushstate时会出现问题。当我接收到事件时,如何知道用户是通过Pushstate API点击了后退或前进历史记录按钮呢?还是我需要自己实现一些东西?
你必须自己实现,这很容易。
pushState
时,给数据对象一个唯一的递增id(uid)。onpopstate
处理函数时,将状态uid与包含上一个状态uid的持久变量进行比较。[a, b, a]
,你会收到 popstate
事件,那么你如何知道它是向后还是向前? - david_adler这个答案适用于单页应用程序、多页应用程序或两者的组合。(为了修复Mesqualito评论中提到的History.length
错误,已进行更正。)
我们可以轻松地监听历史记录堆栈中的新条目。 我们知道,对于每个新条目,规范要求浏览器执行以下操作:
因此,在进入时刻:
新条目位置=上次显示位置+1
解决方案如下:
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
此外还可以查看代码的演示版本。
该解决方案忽略了与应用程序无关的外部页面的历史记录条目,就好像用户从未访问过它们一样。它仅根据最后一个显示的应用程序页面来计算行进方向,而不考虑之间访问的任何外部页面。如果您希望用户将外部条目推送到堆栈中(请参见Atomosk的评论),则可能需要一种解决方法。
history.length
总是会产生相同的数字(在我的情况下为50),因此使得这个解决方案始终返回0作为方向,因为所有状态条目都具有相同的位置。 - Mesqalito