Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
The community reviewed whether to reopen this question 3 years ago and left it closed:
Original close reason(s) were not resolved
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(9)
location.hash
比history.pushState
方法。pushState
方法的优点是您可以将状态绑定到历史条目。如果您不需要此状态对象,我建议使用
location.hash
属性,以便与旧版浏览器具有更好的兼容性。location.hash
has a better support than thehistory.pushState
method.The advantage of the
pushState
method 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.hash
property, to have better compatibility with older browsers.Pushstate 是未来。它更好是因为:
有关更多信息,请参阅 Github 设计师的演讲:http://warpspire.com/talks/responsive/
Pushstate is the future. It's better because:
See this talk from Github designer for more: http://warpspire.com/talks/responsive/
这是一个相当老的问题(在本回复时已超过 5 年),但对现有回复的很多评论都要求根据“当前”状态进行更新。
事情是这样的:
所有主流浏览器都支持 HTML5 的 PushState。如果您也支持旧版浏览器,history.js 提供了一个很棒的polyfill,让您可以使用pushState原生并让它轻松回退到旧版浏览器的旧版 URL。然而,现在原生支持pushState并不意味着它就是正确的选择。
有一个非常重要的观点在任何旧的答案中都没有提出,那就是哈希 URL 和 PushState URL 不仅在显示方式上不同,而且实际上在工作方式上也不同。两者之间的这种根本区别可能会导致您选择其中之一。
PushState 更漂亮、更干净,可用于在您的网站/应用程序中完全伪造导航。例如,GitHub 用它来隐形地替换所有导航。当您单击其网站上的任何链接时,JavaScript 用于拦截该单击并将其转换为 AJAX 请求,该请求会更新页面内容而无需加载新页面,而地址栏中的 URL 会发生更改以匹配之前的内容取来的。 这就是pushState 的用途。
就 GitHub 而言, http://mysite/page1 和 http://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 或本地磁盘上托管此页面。
现在,如果您使用哈希网址,则用户将看到并与之交互的网址将是 http://mysite /mainpage#/charts/1 这是一个有效的真实网址。浏览器知道只有一页,无论用户复制并粘贴链接还是为其添加书签,您只需在 JavaScript 中处理哈希状态,不需要任何服务器端魔法即可使事情正常工作。
似乎没有人提到的是pushState 和哈希链接并不相互排斥。 PushState 只是一个 API,用于操作用户可见的浏览器位置,并在现代浏览器中实现可靠的后退/前进导航。它没有说明您的 URL 方案应该是什么样子。
2017 年,Google 和几乎所有其他支持 JS 的机器人都可以理解哈希 URL 并很好地遍历它们。 Google 希望您使用#! SEO 令人厌恶
最大化的目的,但即使您不这样做,您的网站也可以正常导航。
正确的答案是使用最适合您需求的东西。如果您有真实的 URL 并且想要在它们之间伪造导航,请使用 PushState 并继续(对于较旧的浏览器,可以选择使用 polyfill)。但如果您有一个单页应用程序,请不要假装不这样做(除非您有充分的理由)。使用哈希 URL 可以让您的生活更轻松,并且不会引入不必要的问题,然后使用 PushState 操作这些哈希 URL 以利用更好的后退/前进支持。。
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.
Here's the deal:
HTML5's pushState is supported on all major browsers. If you are supporting older browsers too, history.js provides 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.
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.
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.
In GitHub's case, http://mysite/page1 and http://mysite/page2 are 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.
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.
The user loads your single page app: 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/1 or you use pushState and trick it to becoming 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.
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.
Now if you used hash urls, your URL that the user would have seen and interacted with would have been http://mysite/mainpage#/charts/1 and 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.
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 navigation in modern browsers. It says nothing about what your URL scheme should look like.
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.
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.
history.pushState
比location.hash
更好。但这是 HTML5 的功能。所以最好有一个像下面这样的后备方法。history.pushState
is better thanlocation.hash
. but it is a HTML5 feature. so always better to have a fallback method like below.我同意其他答案,但这里有一些支持
location.hash
的论点:编辑的 URL:我忘记了
a href
)。因此您不必设置点击侦听器,这提高了性能并减少了代码大小。I agree with the other answers, but here are a few arguments in favor of
location.hash
:edit: I forgot one
a href
). So you don't have to set up click listeners, which improves performance and reduces code size.window.location.hash 与 HTML5 History.pushstate 的优点/缺点很大程度上取决于您希望页面降级的具体程度。
在这里,您可能对两种不同场景中的优雅降级感兴趣:
第一个是未启用 JavaScript 的客户端,或者是访问您网站的自动机器人/爬虫。从 SEO 的角度来看,这一点尤其重要。如果您的网页/网络应用程序使用哈希 URL,则这些最终用户将无法获得通过这些链接提供的内容。如果您仅通过哈希 URL 提供内容部分且没有后备,这绝对是一个问题。但是,如果您使用哈希标签链接来修改应用程序状态,那么如果页面降级,应用程序状态就不会保留任何意义,这绝对不是问题。
作为一个示例,请考虑这样一个场景:您的页面在选项卡式布局小部件的三个选项卡中包含三个文本部分。现在有两种可能的情况:在第一种情况下,您将在页面加载期间加载所有内容 - 选项卡式小部件将仅用于隐藏其他部分并显示特定部分。因此,如果您在用于构造选项卡拇指的链接中使用哈希 URL,则您仅使用它们来更改客户端应用程序状态。当 javascript 关闭/不可用时,只是用于构造选项卡式布局的 javascript 不会运行,并且所有内容立即可用 - 一个合理的优雅回退。在这种情况下,不同的应用程序状态根本不存在,因此哈希 URL 降级为仅指向 html 中的锚点 - 预期目的。
如果您在这种情况下使用 html5 Pushstate,而不是 hash-urls,那将是一个坏主意。用户可能会为特定选项卡的链接添加书签的原因。因为您的服务器必须获取该 url 并向用户呈现他所期望的客户端状态。这对于客户端应该负责自己的状态管理的瘦服务器架构来说并不好。您当然可以忽略服务器端的这一方面,并让客户端在页面加载时一开始就检查 url,然后切换到适当的应用程序状态。但这仍然不是一个好主意,因为您的服务器端路由系统关心它应该忽略的额外 url 片段的开销,因为从美学角度来看,它根本不应该担心该片段。这完全符合 hash-url 的设计要求,强烈建议使用它们。如果在这三个部分中,当单击特定选项卡拇指时动态加载文本,那么使用 hash-url 并不是一个好主意。原因是如果 JavaScript 不可用,用户将无法访问链接的内容。这对于 SEO 来说尤其不利。在这种情况下,如果您在服务器端处理 url(在正常情况下会被“劫持”和“ajaxified”)以使内容通常可用,那么从最终用户体验和 SEO 的角度来看,这都是非常好的。
第二种情况是客户端的浏览器过时,不支持 html5 推送状态。虽然上述观点仍然成立,但此外我还认为,强迫没有 Pushstate 的用户与 no-javascript 具有相同程度的降级是不合理的。许多最终用户根本不知道为什么他们会收到降级版本。
我建议您不要总是遵循使用最新技术的教条动机,并根据您的使用场景确定最佳选择。
The advantages/disadvantages of window.location.hash vs HTML5 history.pushstate are largely determined by how exactly you want your page to degrade.
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.
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 "hijacked" 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.
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.
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.
目前,所有现代浏览器都支持
pushState
。因此,pushState
比location.hash
更好,但它是 HTML5 功能。所以,location.hash 并没有消亡,事实上它还会存在很长很长一段时间。
使用此功能的一个好方法是使用支持
pushState
的库,但也可以优雅地降级为使用location.hash
。示例 - https://github.com/browserstate/history.js
此外,
location.hash
对于跳转到命名锚点仍然有用。pushState
将为构建 Web 应用程序提供巨大帮助。我期待着使用它。Currently,
pushState
is supported by all modern browsers. ThereforepushState
is better thanlocation.hash
, but it is a HTML5 feature.So,
location.hash
is not dead, in fact it will be around for a long, long time.A good way to use this is with a lib that supports
pushState
, but also gracefully degrades to usinglocation.hash
.Example - https://github.com/browserstate/history.js
Moreover
location.hash
will still be useful for jumping to named anchors.pushState
will be a tremendous help in building web apps. I look forward to using it.我个人更喜欢pushState,因为它使URL 看起来更漂亮,而且我认为这对于用户体验很重要。
您可以使用 history.js polyfill< 来将
history.pushState
与哈希回退结合使用< /a> 如果您想使用pushState,但又不想遇到旧版浏览器支持的问题。I personally prefer pushState because it makes nicer looking URLs and I think that is important for user experience.
You can use
history.pushState
with a hash fallback using the history.js polyfill if you want to use pushState, but don't want to have issues with older browser support.我在该线程中没有看到一个非常小的差异:
设置
window.location.hash
将强制立即滚动跳转到文档中的新哈希元素(至少在我使用的浏览器中) )。如果您想要平滑滚动,但也希望网址栏中的哈希值更新/更改,则必须使用window.history.pushState
,如下所示:One very small difference I don't see noted anywhere in this thread:
Setting
window.location.hash
will force an immediate scroll jump to the new hash element in the document (at least in the browsers I have). If you want a smooth scroll but also want the hash in the url bar to update/change, you'll have to usewindow.history.pushState
like this: