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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9340121/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 22:37:41  来源:igfitidea点击:

What are the differences between history.pushState & location.hash?

htmlurlpushstatefragment-identifier

提问by Krueger

I'm trying to update the URL using either

我正在尝试使用以下任一方法更新 URL

  • window.location.hashor
  • history.pushState.
  • window.location.hash或者
  • history.pushState.

What are the differences / advantages of each?

每个的区别/优势是什么?

回答by Rob W

location.hashhas a better support than the history.pushStatemethod.
The advantage of the pushStatemethod is that you can bind a state to the history entry.
If you don't need this state object, I recommend to use the location.hashproperty, to have a better compatibility with older browsers.

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"}

回答by Mauvis Ledford

Pushstate is the future. It's better because:

Pushstate 是未来。更好,因为:

  1. It looks cleaner.
  2. On revisit of a deep link you can actually surface real serverside data to support things like SEO and Facebook Open Graph (both send spiders to scrape the html of your page).
  3. Servers don't have access to hash tags data so you don't see it in your server logs so it helps some with analytics.
  4. It helps fix hash tag issues. For example I had an Nginx rewrite to redirect users visiting my app to the same https url. It works in all browsers but Safari which will redirect you to just the domain without the hash (so annoying)!
  5. You can actually use hash tag for what is was meant for, deep linking to sections of long pages.
  6. You can fallback to using real HTTP backend requests for browser that don't support push state OR you can fallback to using hash tag. Both require extra implementation but are easily doable with a little work.
  1. 它看起来更干净。
  2. 在重新访问深层链接时,您实际上可以显示真实的服务器端数据以支持诸如 SEO 和 Facebook Open Graph(两者都发送蜘蛛来抓取页面的 html)之类的东西。
  3. 服务器无权访问哈希标签数据,因此您不会在服务器日志中看到它,因此它有助于分析。
  4. 它有助于解决哈希标签问题。例如,我有一个 Nginx 重写,将访问我的应用程序的用户重定向到相同的 https url。它适用于所有浏览器,但 Safari 会将您重定向到没有哈希值的域(太烦人了)!
  5. 您实际上可以使用哈希标签来表示其含义,深层链接到长页面的部分。
  6. 您可以回退到对不支持推送状态的浏览器使用真实的 HTTP 后端请求,或者您可以回退到使用哈希标签。两者都需要额外的实现,但只需少量工作即可轻松实现。

See this talk from Github designer for more: http://warpspire.com/talks/responsive/

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

回答by Chamika Sandamal

history.pushStateis better than location.hash. but it is a HTML5 feature. so always better to have a fallback method like below.

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

if (typeof(window.history.pushState) == 'function') {
    window.history.pushState(null, path, path);
} else {
    window.location.hash = '#!' + path;
}

回答by user123444555621

I agree with the other answers, but here are a few arguments in favor oflocation.hash:

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

  • it works in every browser, including Internet ExploderTM
  • history.pushState is a developing standard, and the API may change in the future
  • if the users opens a link in a new window/tab, a hash-URL makes sure there is no server request needed to load the page (if the correct caching headers are set)
  • The server configuration is easy, since all the server ever sees is the URL without hash-part
  • 它适用于所有浏览器,包括 Internet Exploder TM
  • history.pushState 是一个发展中的标准,API 未来可能会发生变化
  • 如果用户在新窗口/选项卡中打开链接,则哈希 URL 可确保加载页面不需要服务器请求(如果设置了正确的缓存标头)
  • 服务器配置很简单,因为所有服务器看到的都是没有哈希部分的 URL

edit: I forgot one

编辑:我忘记了一个

  • with hashtags, you can use real links (a href). So you don't have to set up click listeners, which improves performance and reduces code size.
  • 使用主题标签,您可以使用真实链接 ( a href)。因此,您不必设置点击侦听器,从而提高性能并减少代码大小。

回答by Mahmoud Al-Qudsi

This is a rather old question (5 years+ at the time of this reply) but a lot of comments on existing replies are asking for an update based on the "current" state of things.

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

Here's the deal:

这是交易:

HTML5's pushState is supported on all major browsers. If you are supporting older browsers too, history.jsprovides a great polyfill that lets you use pushState natively and have it easily fall back to legacy URLs for older browsers. Now that pushState is natively supported does not mean, however, that it is definitively the way to go.

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

There is a very important point that was not raised in any of the older answers and that is that hash URLs and pushState URLs are not only different in the way they appear, but they are actually different in the way they work, too. This fundamental difference between the two might lead you to choose one over the other.

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

pushState is prettier and cleaner and can be used to completely fake navigation on your site/in your app. For example, GitHub uses it to replace all navigation invisibly. When you click any link on their site, javascript is used to intercept that click and turn it into an AJAX request that updates the contents of the page without loading a new page, while the URL in the location bar changes to match the content that was fetched. This is what pushState was meant to be used for.

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

In GitHub's case, http://mysite/page1and http://mysite/page2are both valid URLs. They are "real" links with "real" content, and initially visiting either page goes through the traditional MVC approach. GitHub uses pushState for navigation in modern browsers, but does not require it - i.e. pushState is used as a "feature add" to (in their opinion) lead to a better user experience when it comes to navigation. When you copy the link in the browser address bar, you are copying a link that was formed via javascript & pushState, but a link that is nevertheless real and valid.

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

However, if you are starting from scratching and creating a single page app and are not using an MVC framework, chances are that you actually only have a single page, especially if you are not using a dynamic backend (i.e. content is all retrieved via javascript, never generated by a server). In this case, if you use pushState over hash urls, you will need to handle the case that the URL in the browser is not the real URL. I will illustrate.

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

The user loads your single page app: http://mysite/mainpage

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

At this point, the browser bar contains the real link to your app, and will take the user to the same view they currently see: the main page. Now they click a link that will take them to a "page" showing the details of some activity. At this point, you want to update the location bar to indicate the change in state. You either use a hash URL and your location bar looks like http://mysite/mainpage#charts/1or you use pushState and trick it to becoming http://mysite/mainpage/charts/1

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

If you used pushState, that is not a real link. Navigating via the browser's back/forward buttons will work great and the user will go from the main page to the detail page in both the location bar and in the app (presuming you handle the state change correctly), but if the user bookmarks this link or copies and pastes the link to share it, additional server-side voodoo will be required.

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

You will need to redirect requests to /mainpage/charts/1 to /mainpage and then use JS to resolve the actual URL and carry out the intended state change operation. A server redirect is absolutely required. You cannot host this page on AWS or on your local disk without a scriptable http server.

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

Now if you used hash urls, your URL that the user would have seen and interacted with would have been http://mysite/mainpage#/charts/1and that is a valid, real url. Browsers understand that there is just one page, and whether the user copies and pastes the link or bookmarks it, you just have to handle the hash state in javascript and do not need any server-side magic to make things work.

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

What no one seems to mention is that pushState and hash links are not mutually exclusive. pushState is just an API to manipulate the browser location that is visible to the user and implement reliable back/forward navigationin modern browsers. It says nothing about what your URL scheme should look like.

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

In 2017, Google and just about every other JS-capable bot understand hash URLs and traverse them just fine. Google wants you to use the #! abomination for SEO maximization purposes, but even if you don't, your site will be navigable just fine.

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

The correct answer is to use whatever fits your needs best. If you have real URLs and want to fake navigation between them, use pushState and carry on (optionally with a polyfill for older browsers). But if you have a single-page app, don't pretend not to (unless you have a very good reason). Use hash URLs to make your life easier and not introduce unnecessary problems and then use pushState to manipulate those hash URLs to take advantage of better back/forward support.

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

回答by lorefnon

The advantages/disadvantages of window.location.hash vs HTML5 history.pushstate are largely determined by how exactly you want your page to degrade.

window.location.hash 与 HTML5 history.pushstate 的优缺点在很大程度上取决于您希望页面降级的准确程度。

Here, you might be interested in graceful degradation in two different scenarios :

在这里,您可能对两种不同场景下的优雅降级感兴趣:

The first one being a client which does not have javascript enabled, or an automated bot/crawler visiting your site. This is particularly important from an SEO perspective. If your web-page/web-application uses hash-urls then content that is available through these links is not available to these end-users. This is definitively a problem if you are making sections of content available only via hash-urls with no fallbacks. However it is definitely not a problem if you are using hash-tag links to modify application state which simply don't retain meaning if the page degrades.

第一个是未启用 javascript 的客户端,或访问您网站的自动机器人/爬虫。从 SEO 的角度来看,这尤其重要。如果您的网页/网络应用程序使用 hash-url,那么这些最终用户将无法通过这些链接获得的内容。如果您仅通过哈希 url 提供内容部分而没有回退,这绝对是一个问题。但是,如果您使用哈希标签链接来修改应用程序状态,这绝对不是问题,如果页面降级,这些状态根本不会保留意义。

As an example consider a scenario where you have a page with three sections of text available in three tabs in a tabbed-layout widget. Now there are two possible scenarios : In the first, you would be loading all the content during the page load - and the tabbed widget will simply serve to hide other sections and show a particular section. So if you use hash-urls in the links you use to construct the tab thumbs, you are using them only to change the client-side application state. When javascript is turned off/is not available, simply the javascript used to construct the tabbed layout does not run, and all the content is immediately available - a reasonable graceful fallback. The different application states simply don't exist in this case and so the hash-urls degrade back to just pointing to anchors in html - the intended purpose. Instead of hash-urls if you were to use html5 pushstate in this case, it would be a bad idea. The reason if that a user might bookmark the link to a particular tab. Because your server would have to take that url and present the user with the client side state which he is expecting. This is not good for a thin server architecture where the client-side should take care of its own state management. You can ofcourse ignore that aspect on server side and let the client check the url right at the beginning upon page load and then switch to appropriate application state. But still it is not a good idea because your server side routing system is concerned with the overhead of additional url fragments which it should ignore, where as it should not be bothered about that fragment at all from an aesthetic perspective. This maps exactly to the requirement for which hash-urls were designed and using them is strongly recommended. If instead in the three sections, the text gets loaded dynamically when a particular tab thumb is clicked, then using hash-urls is not a good idea. The reason being the user will simply have no way to access the linked content if javascript is not available. This is particularly bad for SEO. In this scenario if you handle urls (which would in normal scenario be "hiHymaned" and "ajaxified") on the server side to make content available in general it is excellent both from point of view of end-user experience as well as SEO.

举个例子,考虑这样一个场景,你有一个页面,在选项卡式布局小部件的三个选项卡中提供三个文本部分。现在有两种可能的情况:在第一种情况下,您将在页面加载期间加载所有内容 - 选项卡式小部件将仅用于隐藏其他部分并显示特定部分。因此,如果您在用于构建选项卡缩略图的链接中使用哈希 url,则您仅使用它们来更改客户端应用程序状态。当 javascript 关闭/不可用时,仅用于构建选项卡式布局的 javascript 不会运行,并且所有内容都立即可用 - 一个合理的优雅回退。在这种情况下,不同的应用程序状态根本不存在,因此哈希 url 降级回仅指向 html 中的锚点 - 预期目的。如果你在这种情况下使用 html5 pushstate 而不是 hash-urls,这将是一个坏主意。用户可能会将指向特定选项卡的链接加入书签的原因。因为您的服务器将不得不采用该 url 并向用户呈现他所期望的客户端状态。这对于客户端应该负责自己的状态管理的瘦服务器架构来说并不好。您当然可以在服务器端忽略该方面,让客户端在页面加载时从一开始就检查 url,然后切换到适当的应用程序状态。但这仍然不是一个好主意,因为您的服务器端路由系统关注它应该忽略的额外 url 片段的开销,因为从美学的角度来看,它根本不应该打扰该片段。这完全符合设计 hash-url 的要求,强烈建议使用它们。如果在这三个部分中,文本在单击特定选项卡缩略图时动态加载,则使用 hash-urls 不是一个好主意。原因是如果 javascript 不可用,用户将无法访问链接的内容。这对 SEO 尤其不利。在这种情况下,如果您在服务器端处理 url(在正常情况下会被“劫持”和“ajaxified”)以使内容可用,那么从最终用户体验和 SEO 的角度来看,这都是非常好的。那么使用 hash-urls 不是一个好主意。原因是如果 javascript 不可用,用户将无法访问链接的内容。这对 SEO 尤其不利。在这种情况下,如果您在服务器端处理 url(在正常情况下会被“劫持”和“ajaxified”)以使内容可用,那么从最终用户体验和 SEO 的角度来看,这都是非常好的。那么使用 hash-urls 不是一个好主意。原因是如果 javascript 不可用,用户将无法访问链接的内容。这对 SEO 尤其不利。在这种情况下,如果您在服务器端处理 url(在正常情况下会被“劫持”和“ajaxified”)以使内容可用,那么从最终用户体验和 SEO 的角度来看,这都是非常好的。

The second scenario is a client who has an antiquated browser which does not support html5 pushstates. While the above points still hold, in addition I would also argue that forcing users with no pushstate with the same level of degradation as no-javascript is not justifiable. A lot of end-users will simply have no idea why they are receiving a degraded version.

第二种情况是具有不支持 html5 pushstates 的过时浏览器的客户端。虽然以上几点仍然成立,但我还认为,强制用户使用与 no-javascript 相同级别的降级没有 pushstate 是不合理的。许多最终用户根本不知道为什么他们会收到降级版本。

I would recommend you not to tag along with dogmatic motivation of using the latest technology always, and decide the best option for your usage scenario.

我建议你不要总是带着教条式的动机去使用最新技术,而要为你的使用场景决定最佳选择。

回答by Shivam Mathur

Currently, pushStateis supported by all modern browsers. Therefore pushStateis better than location.hash, but it is a HTML5 feature.

目前,pushState所有现代浏览器都支持。因此pushState优于location.hash,但它是一个 HTML5 功能。

So, location.hashis not dead, in fact it will be around for a long, long time.

所以,location.hash并没有死,事实上它会存在很长很长一段时间。

A good way to use this is with a lib that supports pushState, but also gracefully degrades to using location.hash.
Example- https://github.com/browserstate/history.js

使用一个很好的方法是使用一个lib支持pushState,同时也缓慢下降到使用location.hash
示例- https://github.com/browserstate/history.js

Moreover location.hashwill still be useful for jumping to named anchors. pushStatewill be a tremendous help in building web apps. I look forward to using it.

此外,location.hash对于跳转到命名锚点仍然很有用。 pushState将在构建 Web 应用程序方面提供巨大帮助。我期待着使用它。

回答by kbjr

I personally prefer pushState because it makes nicer looking URLs and I think that is important for user experience.

我个人更喜欢 pushState,因为它使 URL 看起来更漂亮,而且我认为这对用户体验很重要。

You can use history.pushStatewith a hash fallback using the history.js polyfillif you want to use pushState, but don't want to have issues with older browser support.

如果你想使用 pushState,你可以使用history.js polyfillhistory.pushState使用散列回退,但不希望旧浏览器支持出现问题。