history.pushState 和 location.hash 有什么区别?

IT技术 javascript html url pushstate fragment-identifier
2021-02-23 00:12:36

我想使用window.location.hash更新 URL history.pushState

每种方法的区别和优点是什么?

6个回答

location.hashhistory.pushState方法有更好的支持

pushState方法的优点是您可以将状态绑定到历史条目。

如果你不需要这个状态对象,我建议使用该location.hash属性,以更好地与旧浏览器兼容。

location.hash = 'new-hash';
console.log(history.state); // null or undefined

history.pushState({extraData: "some state info"}, '', 'new-hash'); //<---
console.log(history.state); // [object Object] = {"extraData": "some state info"}
啊,当然。所以你的回答真的把它归结起来。hash有更好的支持,同时pushState更强大。
2021-04-22 00:12:36
但是是否可以将 history.state 加入书签或将其发布到 facebook 上?我认为哈希是可能的。它们是完全不同的东西。
2021-04-24 00:12:36
自从提出这个问题 3 年后,现在哪个更好,pushstate 还是 location.hash?
2021-05-12 00:12:36
@Robert 当您为某些内容添加书签时,将使用当前在浏览器中看到的 URL。状态对象与历史条目相关联。因此,它仅在通过浏览历史记录导航到页面时可用(例如浏览器关闭后的会话恢复)。一种方法不排除另一种方法:使用 是合法的history.pushState('some long state cached from server', '', '/posts/id#prefix-some-specific-identifier'),例如,如果应用程序确实需要它。在此示例中,缓存了服务器响应。顺便说一下,哈希也可能是斜线。
2021-05-13 00:12:36
@houshistory.pushStatehistory.replaceStateand usinghistory.state如果您确实需要将数据与历史条目相关联。如果您希望页面状态可添加书签,那么location.hash就足够了(因为书签只能存储页面 URL,而不能存储历史状态)。
2021-05-19 00:12:36

Pushstate 是未来。更好,因为:

  1. 它看起来更干净。
  2. 在重新访问深层链接时,您实际上可以显示真实的服务器端数据以支持诸如 SEO 和 Facebook Open Graph(两者都发送蜘蛛来抓取页面的 html)之类的东西。
  3. 服务器无权访问哈希标签数据,因此您不会在服务器日志中看到它,因此它有助于分析。
  4. 它有助于解决哈希标签问题。例如,我有一个 Nginx 重写,将访问我的应用程序的用户重定向到相同的 https url。它适用于所有浏览器,但 Safari 会将您重定向到没有哈希值的域(太烦人了)!
  5. 您实际上可以使用哈希标记来表示其含义,深层链接到长页面的部分。
  6. 您可以回退到对不支持推送状态的浏览器使用真实的 HTTP 后端请求,或者您可以回退到使用哈希标记。两者都需要额外的实现,但只需少量工作即可轻松实现。

有关更多信息,请参阅 Github 设计师的演讲:http : //warpspire.com/talks/responsive/

但是,Pushstate 有一个小缺点:它会强制服务器在第一次访问时/当您在新选项卡中打开链接页面时为您呈现页面。如果一个人打开 10 个选项卡(比如浏览图库并打开有趣的图片),它比 hashbangs 慢得多,因为根本不使用 ajax。
2021-04-22 00:12:36
你能解释一下吗?假设我访问 example.com/ajax#gallery ,我的浏览器通过 example.com/ajax 下载一些 js,然后该 js 请求并呈现 #gallery。当我在新选项卡中打开 example.com/ajax#image1 时,我的浏览器已经缓存了 example.com/ajax,因此它只需要获取 #image1 并呈现它。据我所知,Pushstate 并非如此。当您在新选项卡中打开 example.com/ajax/image1 (pushstate) 或第一次访问它时,无论 example.com/ajax 的缓存如何,浏览器都必须下载完整页面。如果我错了,我愿意纠正。
2021-04-29 00:12:36
(上下文:在 Facebook 中,图库是基于 ajax 的,单击照片会更改 URL 并放大该照片,将 URL 复制到新选项卡会加载照片的静态页面)。这不是更有利的。考虑这个替代方案:画廊位于 fb.com/#gallery-17 。单击照片可放大照片并将 url 更改为 fb.com/#photo-521。打开多张照片时效率要高得多,因为 fb.com 总是被缓存。
2021-05-12 00:12:36
@Hello World:好的,您在技术上是对的。通常,当使用 pushstate 时,它​​会动态更改 URL,并且不会进行额外的页面加载。如果您右键单击并打开选项卡中的链接,您并没有真正利用动态推送状态的全部意义。单击 Facebook 流中的图像,注意动态 URL 更改,然后将 URL 粘贴到新窗口中。你刚才看到的比你提到的“缺点”更有优势。在这种情况下,它实际上是一种奖励而不是劣势。
2021-05-15 00:12:36
@Hello-World:这是一个假设。对于许多/大多数基于 JavaScript 的框架,它正在做与 hashbangs 完全相同的事情。
2021-05-16 00:12:36

history.pushState比 好location.hash但它是一个 HTML5 功能。所以最好有一个像下面这样的后备方法。

if (typeof(window.history.pushState) == 'function') {
    window.history.pushState(null, path, path);
} else {
    window.location.hash = '#!' + path;
}
自从提出这个问题 3 年后,现在哪个更好,pushstate 还是 location.hash?
2021-04-30 00:12:36
回退在这里没有意义:location.hash 在也支持 pushState 的浏览器上也能正常工作 - 如果您确实需要 pushState(因为您需要存储一个对象),则 location.hash 将无法作为回退。随便选一个。
2021-05-19 00:12:36

这是一个相当古老的问题(在此回复时为 5 年以上),但对现有回复的许多评论都要求根据“当前”状态进行更新。

这是交易:

所有主流浏览器都支持 HTML5 的 pushState。如果您也支持旧版浏览器,history.js提供了一个很棒的 polyfill,让您可以在本机使用 pushState 并让它轻松回退到旧版浏览器的旧版 URL。然而,现在原生支持 pushState 并不意味着它绝对是要走的路。

有一个非常重要的观点在任何较旧的答案中都没有提出,那就是哈希 URL 和 pushState URL 不仅在它们出现的方式上不同,而且实际上它们的工作方式也不同。两者之间的这种根本区别可能会导致您选择一个而不是另一个。

pushState 更漂亮、更干净,可用于在您的网站/应用中完全伪造导航。例如,GitHub 使用它来无形地替换所有导航。当您单击他们网站上的任何链接时,javascript 会拦截该单击并将其转换为 AJAX 请求,该请求会在不加载新页面的情况下更新页面内容,同时地址栏中的 URL 会更改以匹配之前的内容取来的。这就是 pushState 的用途

在 GitHub 的情况下,http://mysite/page1http://mysite/page2都是有效的 URL。它们是具有“真实”内容的“真实”链接,最初访问任一页面都通过传统的 MVC 方法。GitHub 在现代浏览器中使用 pushState 进行导航,但并不需要它 - 即 pushState 用作“功能添加”以(在他们看来)在导航方面带来更好的用户体验。当您复制浏览器地址栏中的链接时,您正在复制通过 javascript 和 pushState 形成的链接,但该链接仍然真实有效。

但是,如果您从头开始创建一个单页应用程序并且没有使用 MVC 框架,那么您实际上只有一个页面,特别是如果您没有使用动态后端(即所有内容都是通过 javascript 检索的) ,从未由服务器生成)。在这种情况下,如果您在哈希 url 上使用 pushState,您将需要处理浏览器中的 URL 不是真实 URL 的情况。我会举例说明。

用户加载您的单页应用程序:http://mysite/mainpage

此时,浏览器栏包含指向您的应用程序的真实链接,并将用户带到他们当前看到的相同视图:主页。现在他们点击一个链接,将他们带到一个“页面”,显示某些活动的详细信息。此时,您要更新位置栏以指示状态的变化。您要么使用哈希 URL 并且您的位置栏看起来像http://mysite/mainpage#charts/1,要么您使用 pushState 并欺骗它成为http://mysite/mainpage/charts/1

如果您使用 pushState,那不是真正的链接通过浏览器的后退/前进按钮导航将非常有效,用户将从主页面转到位置栏和应用程序中的详细信息页面(假设您正确处理状态更改),但如果用户将此链接添加为书签或复制并粘贴链接以共享它,将需要额外的服务器端伏都教。

您需要将 /mainpage/charts/1 的请求重定向到 /mainpage,然后使用 JS 解析实际 URL 并执行预期的状态更改操作。服务器重定向是绝对需要的。如果没有可编写脚本的 http 服务器,您就无法在 AWS 或本地磁盘上托管此页面。

现在,如果您使用哈希 url,那么用户会看到并与之交互的 URL 将是http://mysite/mainpage#/charts/1 并且这是一个有效的真实 url浏览器知道只有一页,无论用户是复制和粘贴链接还是为其添加书签,您只需要在 javascript 中处理散列状态,不需要任何服务器端魔法来使事情工作。

似乎没有人提到pushState 和 hash 链接不是相互排斥的pushState 只是一个 API,用于操作用户可见的浏览器位置在现代浏览器中实现可靠的后退/前进导航它没有说明您的 URL 方案应该是什么样子。

在 2017 年,谷歌和几乎所有其他支持 JS 的机器人都能理解哈希 URL 并很好地遍历它们。Google 希望您使用 #! 出于 SEO 最大化目的而令人憎恶,但即使您不这样做,您的网站也可以正常导航。

正确的答案是使用最适合您需要的任何东西。如果你有真实的 URL 并且想要在它们之间伪造导航,请使用 pushState 并继续(对于旧浏览器可以选择使用 polyfill)。但是如果你有一个单页应用程序,不要假装没有(除非你有很好的理由)。使用哈希 URL 使您的生活更轻松,不会引入不必要的问题,然后使用 pushState 操作这些哈希 URL 以利用更好的后退/前进支持

@FabioLolli 关于最后一句话 - 在我的应用程序中,我有时会发现自己通过pushState操纵位置哈希replaceState例如,最近的一个应用程序在按键上执行搜索。此搜索应更新用于书签/转发等的 URL,但您不希望每次击键都用新条目填充历史堆栈(就像仅操作 会发生的那样location.hash)。相反,我replaceState在打字时使用,然后在一些去抖动超时后或在pushState必要时按回车键执行
2021-04-23 00:12:36
实际上,截至 2015 年 10 月,Google 不希望您使用 #!。webmasters.googleblog.com/2015/10/...
2021-04-29 00:12:36
我不确定你最后一句话的意思:你是不是建议用 location.hash 替换 URL,然后用 pushState 再做一次?那会有什么帮助?据我了解,pushState 的主要问题是书签,但如果我们这样做,我们最终会得到需要重定向魔法的书签 URL 吗?顺便说一句,非常清晰和翔实,试图获得所有这些信息感觉就像在编写一个困难的谜题,在这里你真的触及了与讨论相关的几乎所有内容,谢谢
2021-05-06 00:12:36

我同意其他答案,但这里有一些赞成的 论点location.hash

  • 它适用于所有浏览器,包括 Internet Exploder TM
  • history.pushState 是一个发展中的标准,API 未来可能会发生变化
  • 如果用户在新窗口/选项卡中打开链接,哈希 URL 可确保加载页面不需要服务器请求(如果设置了正确的缓存标头)
  • 服务器配置很简单,因为所有服务器看到的都是没有哈希部分的 URL

编辑:我忘记了一个

  • 使用主题标签,您可以使用真实链接 ( a href)。因此,您不必设置点击侦听器,从而提高性能并减少代码大小。
有没有计划用新标签使 Pushstate 更好?
2021-05-03 00:12:36
谷歌将发送 #! 基于哈希......这需要一些努力......这样做是为了photogallery.classiccars.com
2021-05-13 00:12:36