我一直在做一些研究,似乎 popstate 事件会在历史记录发生更改时触发,但似乎没有内置方法来确定用户是单击后退按钮还是前进按钮浏览器。
我的用例是,当在历史记录中返回或在历史记录中前进时,我在 ajax 应用程序中转换路由时会出现定向动画。我需要确定用户是向后还是向前,这样动画才有意义。遗憾的是 popstate 事件不支持事件的方向。
我还将提到我的应用程序是一个 AngularJS 应用程序,以防有特定角度的答案,尽管更通用的 javascript 解决方案将是最佳的。
我一直在做一些研究,似乎 popstate 事件会在历史记录发生更改时触发,但似乎没有内置方法来确定用户是单击后退按钮还是前进按钮浏览器。
我的用例是,当在历史记录中返回或在历史记录中前进时,我在 ajax 应用程序中转换路由时会出现定向动画。我需要确定用户是向后还是向前,这样动画才有意义。遗憾的是 popstate 事件不支持事件的方向。
我还将提到我的应用程序是一个 AngularJS 应用程序,以防有特定角度的答案,尽管更通用的 javascript 解决方案将是最佳的。
我不确定哪种理解是正确的,但是我对 HTML5 pushstate 的理解是不同的。
推送状态支持仅允许您捕获浏览器 URL 中的更改,否则这些更改将作为请求发送到服务器(您的或其他人的)。目的不是为您提供“前进”和“后退”事件,而更像是一般的“位置更改”事件。然后,您的应用程序的工作就是检查 URL 并找出用户试图去的地方。
可以这样想:如果用户点击了您的应用程序中您想用 javascript 处理的链接怎么办?您将设置一些事件处理程序,它们将捕获点击并以某种方式操纵您的应用程序。所以点击“后退”或“前进”就像点击一个链接,但你得到的只是用户试图查看的 URL——没有将事件绑定到的链接。
那么你怎么知道用户想要做什么呢?您可以使用全局变量或您能想到的任何其他方式来管理状态。如果您想减少代码重复,您可以使用 URL 处理所有应用程序路由。因此,您的点击处理程序不会绑定到特定链接(或一组链接),而是可以捕获浏览器 URL 中的更改,然后确定如何处理新 URL。
BackboneJS 使用 Router 对象执行此操作,其中特定路径与特定路由器功能相关联,从而以特定方式设置应用程序的状态,例如:
MyAppRouter = Backbone.Router.extend({
routes: {
'home': 'setupHomeScreen',
'recipes': 'setupRecipesList',
'recipes/:id': 'setupRecipeScreen'
},
setupHomeScreen: function() {
// ...
},
setupRecipesList: function() {
// ...
},
setupRecipeScreen: function(id) {
// ...
},
// ...
});
请原谅 Angular 问题上的主干代码。我仍在学习 Angular 方式,并且来自 Backbone 背景,这形成了我对 pushstate 的理解。
如果您的视图形成某种层次结构或顺序,则可以将其存储在全局变量中。也许您决定为每个视图提供 ID,然后每次浏览器状态更改时,您将这些 ID 推送到数组中。
var viewHistory = [];
// ... they visited the recipe list. push it into the history
viewHistory.push('recipeList');
// ... they visited a particular recipe. push it into the history
viewHistory.push('recipe:13');
// ... they clicked the "back" button. we know from the URL that they want
// the recipeList, but we don't know if they're trying to go forward or back.
var nextView = 'recipeList';
if (viewHistory.indexOf(nextView) > 0) {
// *** Back Button Clicked ***
// this logic assumes that there is never a recipeList nested
// under another recipeList in the view hierarchy
animateBack(nextView);
// don't forget to remove 'recipeList' from the history
viewHistory.splice(viewHistory.indexOf(nextView), viewHistory.length);
} else {
// *** They arrived some other way ***
animateForward(nextView);
}