【问题标题】:How to tell whether the forward or backward button was pressed using the popstate event如何使用 popstate 事件判断是按下了前进按钮还是后退按钮
【发布时间】:2013-05-12 19:24:39
【问题描述】:

我一直在做一些研究,似乎只要更改历史记录就会触发 popstate 事件,但似乎没有内置方法来确定用户是单击后退按钮还是前进按钮浏览器中的按钮。

我的用例是,在历史记录中返回或前进时,我在 ajax 应用程序中转换路由时会出现定向动画。我需要确定用户是向后还是向前,这样动画才有意义。可惜popstate事件不支持事件的方向。

我还会提到我的应用程序是一个 AngularJS 应用程序,以防有特定角度的答案,尽管更通用的 javascript 解决方案将是最佳的。

【问题讨论】:

  • 为什么不使用变量呢?只需在每个状态中保存一个增量状态 ID 并保存最后一个状态的 ID。弹出时,计算旧状态和新状态之间的差异,看看用户去了哪个“方向”。但是,是的,浏览器原生实现会很好。
  • 是的,这是有道理的。我可以将全局状态存储在应用程序本身中,以确定用户前进的方向。我宁愿不必像那样跟踪,但如果没有办法确定历史的方向,否则我想这就是需要做的事情。谢谢!
  • @Umur 那other question 指定使用pushState 的应用程序。无论如何,我确实在那里发布了一个通用的解决方案。它也可以回答这个 OP 的问题。

标签: javascript angularjs


【解决方案1】:

我不确定哪种理解是正确的,但是我对 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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 2010-10-22
    • 2013-10-11
    • 2014-07-07
    • 1970-01-01
    相关资源
    最近更新 更多