【问题标题】:Modify Address Bar URL in AJAX App to Match Current State修改 AJAX 应用程序中的地址栏 URL 以匹配当前状态
【发布时间】:2010-09-05 07:30:39
【问题描述】:

我正在编写一个 AJAX 应用程序,但是当用户在应用程序中移动时,我希望地址栏中的 URL 能够更新,尽管没有重新加载页面。基本上,我希望他们能够在任何时候添加书签,从而返回到当前状态。

人们如何在 AJAX 应用程序中维护 RESTful?

【问题讨论】:

  • 用于维护你的应用程序的状态,但与“RESTful”无关。
  • window.history.pushState(null,'hi','page1?id=32')
  • 接受的答案是 5 年前写的,与此同时,我们得到了 window.history.pushState,就像@Omu 说的那样。 location.hash 带来了很多问题,最好避免它。
  • 我已经编辑了答案以突出 pushState 方法。

标签: ajax url rest address-bar


【解决方案1】:

执行此操作的方法是在 AJAX 更新导致您希望拥有一个离散 URL 的状态更改时操纵 location.hash。例如,如果您的页面的 url 是:

http://example.com/

如果客户端函数执行了此代码:

// AJAX code to display the "foo" state goes here.

location.hash = 'foo';

然后,浏览器中显示的 URL 将更新为:

http://example.com/#foo

这允许用户为页面的“foo”状态添加书签,并使用浏览器历史记录在状态之间导航。

使用此机制后,您需要在客户端使用 JavaScript 解析出 URL 的哈希部分,以创建并显示适当的初始状态,因为片段标识符(# 之后的部分)不是发送到服务器。

Ben Alman's hashchange plugin 如果您使用的是 jQuery,则让后者变得轻而易举。

【讨论】:

  • 看来你是对的。这是唯一的方法。这似乎是对您建议的一个很好的详细解释:ajaxpatterns.org/Unique_URLs>
  • @buymeasoda 感谢您的编辑;我不确定我在写那部分时在想什么。
  • 哇,这个答案很有帮助。尽管 URL 示例有点令人困惑,但 SO 可能会自动将链接替换为标题。用 example.com 和 example.com/#foo 之类的内容替换它们怎么样,这样我们就可以以纯文本形式查看整个 url。
  • @Pascal 你可以,但只能在支持 HTML5 的 pushState 的浏览器中。这里有很好的信息:diveintohtml5.info/history.html
  • 我最终成为了 history.js 的忠实粉丝,以涵盖浏览器兼容性的基础github.com/andreasbernhard/history.js
【解决方案2】:

查看诸如 book.cakephp.org 之类的网站。此站点更改 URL 而不使用哈希并使用 AJAX。我不确定它是如何做到的,但我一直在试图弄清楚。如果有人知道,请告诉我。

在查看某个项目中的导航时也可以访问 github.com。

【讨论】:

  • 大约一周前,我在 GitHub 上注意到了这一点。他们到底是怎么做到的?必须回去检查。
  • 他们似乎在使用 javascript 函数 pushState()。这会增加浏览器的历史记录。了解更多;这很有趣也很酷。
  • 谢谢,这正是我想要的。我想知道github是如何做到的。起初我以为它必须重新加载,但只有 AJAX 请求。在 Opera 中,它确实重新加载了页面。
  • fb 在浏览不同组的页面时使用了类似的技术。您有一个左侧导航列,其中提到了不同的组。当您单击特定组名称时,url 会发生变化,并且只有主内容窗格的内容会随着 url 发生变化(无哈希)。因此,当用户重新加载页面时,他们不会重定向到主页,而是重定向到组的页面。
【解决方案3】:

在使用 Ajax 时,作者不太可能想要重新加载或重定向他的访问者。 但是为什么不使用 HTML5 的pushState/replaceState呢?

您可以随意修改地址栏。 Get natural looking urls, with AJAX.

查看我最新项目的代码: http://iesus.se/

【讨论】:

    【解决方案4】:

    这与凯文所说的相似。您可以将您的客户端状态作为一些 javascript 对象,当您想要保存状态时,您可以序列化该对象(使用 JSON 和 base64 编码)。然后,您可以将 href 的片段设置为此字符串。

    var encodedState = base64(json(state));
    var newLocation = oldLocationWithoutFragment + "#" + encodedState;
    
    document.location = newLocation; // adds new entry in browser history
    document.location.replace(newLocation); // replaces current entry in browser history
    

    第一种方式会将新状态视为新位置(因此后退按钮会将它们带到上一个位置)。后者没有。

    【讨论】:

    • 有没有办法在不刷新页面的情况下将条目添加到书签历史记录?设置位置(如您的第一个示例)将导致刷新,不是吗?
    • 执行 document.location.replace 也会将浏览器重定向到该 url(刚刚在 chrome 控制台中尝试过)
    【解决方案5】:

    SWFAddress 在 Flash 和 Javascript 项目中工作,让您可以创建可收藏的 URL(使用上面提到的哈希方法)并为您提供后退按钮支持。

    http://www.asual.com/swfaddress/

    【讨论】:

      【解决方案6】:

      window.location.hash 方法是首选的做事方式。有关如何执行此操作的说明, Ajax Patterns - Unique URLs.

      YUI 以模块的形式实现了这种模式,其中包括 IE 特定的解决方法,用于使后退按钮与使用哈希重写地址一起工作。 YUI Browser History Manager.

      其他框架也有类似的实现。重要的一点是,如果您希望历史记录与重写地址一起工作,不同的浏览器需要不同的处理方式。 (这在第一篇链接文章中有详细说明。)

      IE 需要基于 iframe 的 hack,Firefox 将使用相同的方法生成双重历史记录。

      【讨论】:

        【解决方案7】:

        如果 OP 或其他人仍在寻找修改浏览器历史记录以启用状态的方法,则按照 IESUS 的建议,使用 pushState 和 replaceState 是现在的“正确”方法。与 location.hash 相比,它的主要优势似乎在于它创建了实际的 URL,而不仅仅是哈希。如果保存了使用哈希的浏览器历史记录,然后在禁用 JavaScript 的情况下重新访问,则应用程序将无法运行,因为哈希不会发送到服务器。但是,如果已使用 pushState,则整个路由将被发送到服务器,然后您可以构建该服务器以适当地响应路由。我看到了一个例子,在服务器端和客户端都使用了相同的胡子模板。如果客户端启用了 JavaScript,他会通过避免往返服务器而获得快速响应,但如果没有 JavaScript,应用程序将完全正常工作。因此,应用程序可以在没有 JavaScript 的情况下正常降级。

        另外,我相信有一些框架,名称类似于 history.js。对于支持 HTML5 的浏览器,它使用 pushState,但如果浏览器不支持它,它会自动回退到使用哈希。

        【讨论】:

          【解决方案8】:

          检查用户是否在页面中,当您单击 URL 栏时,JavaScript 会说您不在页面中。 如果您更改 URL 栏并在其中按带有符号“#”的“ENTER”,然后您再次进入该页面,而无需使用鼠标光标手动单击该页面,那么来自 JavaScript 的键盘事件命令 (document.onkeypress) 将能够检查它是否进入并激活 JavaScript 以进行重定向。 您可以使用 window.onfocus 检查用户是否在页面中,并使用 window.onblur 检查他是否在页面外。

          是的,有可能。

          ;)

          【讨论】:

          • 当用户使用 # 符号编辑 url 栏时,这是我看到的优雅更改页面的方式。
          猜你喜欢
          • 2020-07-24
          • 2018-10-08
          • 2015-01-21
          • 2017-05-31
          • 1970-01-01
          • 2014-03-29
          • 2013-06-02
          • 1970-01-01
          • 2011-08-19
          相关资源
          最近更新 更多