2012-02-18 90 views

回答

25

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

但是有可能为history.state添加书签或将其发布到Facebook上?我认为这可能与哈希。他们是完全不同的东西。 – Robert 2012-07-15 00:19:57

+0

@Robert当您收藏某些内容时,会使用当前在浏览器中看到的URL。状态对象与历史记录条目相关联。而且,只有当浏览历史记录(例如浏览器关闭后的会话恢复)导航到页面时才可用。一种方法不排除另一种方法:使用'history.pushState'('从服务器缓存的一些长状态','','/ posts/id#prefix-some-specific-identifier')'是合法的,例如,如果应用程序确实需要它。在这个例子中,服务器响应被缓存。顺便说一句,哈希也可能是斜线。 – 2012-07-15 08:29:57

+1

啊,当然。所以你的回答真的让它失望了。''hash'有更好的支持,'pushState'更强大。 – Robert 2012-07-16 01:54:02

13

history.pushState要好于location.hash。但它是一个HTML5功能。所以最好有一个像下面这样的回退方法。

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

自问题出现3年后,现在哪个更好,pushstate或location.hash? – hous 2015-11-19 16:54:47

22

Pushstate是未来。这是因为:

  1. 它看起来更干净。
  2. 在重温深层链接时,您实际上可以展示真实的服务器端数据,以支持诸如SEO和Facebook Open Graph(都会发送蜘蛛来抓取页面的html)等内容。
  3. 服务器无权访问散列标签数据,因此您无法在服务器日志中看到它,所以它可以帮助一些分析人员。
  4. 它有助于修复哈希标记问题。例如,我有一个Nginx重写,将访问我的应用的用户重定向到相同的https网址。它适用于所有的浏览器,但Safari会将你重定向到没有散列的域名(如此令人讨厌)!
  5. 实际上,您可以使用散列标签来表示深层链接到长页面的部分。
  6. 您可以使用真实的HTTP后端请求来支持不支持推送状态的浏览器,或者您可以退回到使用哈希标记。两者都需要额外的实施,但只需一点工作即可轻松完成。

见从GitHub的设计师这次谈话的更多:http://warpspire.com/talks/responsive/

+1

Pushstate虽然有一个小缺点:它会强制服务器在首次访问时/当您在新选项卡中打开链接页时为您呈现页面。如果一个人打开了10个标签页(说,浏览一个图库并打开有趣的图片),它比hashbangs慢得多,因为ajax根本不用。 – 2014-06-02 14:51:14

+1

@ Hello-World:这是一个假设。对于许多/大多数基于JavaScript的框架,它正在做与hashbangs完全相同的事情。 – 2014-06-25 06:02:57

+0

你能解释一下吗?假设我访问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上的缓存如何,浏览器都必须下载完整页面。如果我错了,我可以改正。 – 2014-06-25 08:11:51

7

我同意其他的答案,但这里有几个参数赞成location.hash

  • 它在每浏览器,包括Internet Exploder TM
  • history.pushState是一个开发标准,API未来可能会更改
  • 如果用户在新窗口/选项卡中打开链接,散列URL确保没有加载页面所需的服务器请求(如果设置了正确的缓存标头)
  • 服务器配置非常简单,因为所有的服务器曾经看到的网址是没有哈希部分

编辑:我忘了一个

  • 用#标签,你可以使用真正的链接(a href)。因此,您不必设置点击侦听器,这可以提高性能并减少代码大小。
+0

Google会发送#!基于浏览器的哈希...需要一点点努力...为photogallery.classiccars.com做了这个 – Tracker1 2012-07-15 03:27:48

+0

有没有计划让Pushstate更好地使用新的选项卡? – 2014-07-03 09:24:11

+0

变通方法也很受欢迎 – 2014-07-03 09:51:30

7

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

在这里,你可能会感兴趣的优雅降级两种不同的情况:

第一个是客户端不支持JavaScript,或者自动机器人/网络爬虫访问您的网站。从SEO角度来看,这一点尤为重要。如果您的网页/网页应用程序使用哈希URL,那么通过这些链接可用的内容不可用于这些最终用户。如果您仅通过哈希URL创建内容部分而没有回退,则这确实是一个问题。然而,如果您使用散列标签链接来修改应用程序状态,但如果页面降级时不会保留含义,这绝对不是问题。

作为示例,请考虑一个场景,其中有一个页面,其中包含三个选项卡中的三个文本部分。现在有两种可能的情况:第一种情况是,您将在加载页面期间加载所有内容 - 并且标签式小部件仅用于隐藏其他部分并显示特定部分。因此,如果您在用于构建标签大拇指的链接中使用散列URL,则仅使用它们来更改客户端应用程序状态。当javascript关闭/不可用时,只需用于构建选项卡式布局的JavaScript不会运行,并且所有内容都立即可用 - 这是一种合理的优雅回退。在这种情况下,不同的应用程序状态根本就不存在,所以散列URL会降低到仅指向html中的锚点 - 预期的目的。 在这种情况下,如果您要使用html5 pushstate,而不是哈希URL,这将是一个坏主意。如果用户可能会将链接添加到特定标签的原因。因为你的服务器将不得不采取该网址,并向用户展示他期望的客户端状态。这对于客户端应该照顾自己的状态管理的瘦服务器体系结构来说并不合适。您可以忽略服务器端的这一方面,并​​让客户端在页面加载时从头开始检查URL,然后切换到适当的应用程序状态。但是这仍然不是一个好主意,因为你的服务器端路由系统关心的是额外url碎片的开销,它应该忽略它,因为从审美的角度来看,它应该不会被这个碎片困扰。这完全符合哈希网址的设计要求,强烈建议使用它们。如果相反在三个部分中,当单击特定的选项卡缩略图时会动态加载文本,那么使用散列URL不是一个好主意。如果javascript不可用,原因是用户将无法访问链接的内容。这对搜索引擎优化尤其不利。在这种情况下,如果您在服务器端处理URL(通常情况下会被“劫持”和“混淆”)以使内容一般可用,则从最终用户体验以及SEO的角度来看都是非常好的。

第二种情况是客户端拥有不支持html5 pushstate的过时浏览器。虽然上述观点仍然存在,但是我还会争辩说,强制用户没有与没有JavaScript的降级相同级别的推送状态是不合理的。许多最终用户根本不知道他们为什么收到降级版本。

我建议您不要随时使用最新技术的教条式动机标记,并为您的使用场景决定最佳选择。

+1

很好的答案,但我不太同意SEO部分。您可以使用散列网址,并且仍然可以将您的网页编入索引。请参阅https://developers.google.com/webmasters/ajax-crawling/ – user123444555621 2012-07-09 22:00:03

+0

@ Pumbaa80我同意 – 2012-07-14 14:37:11

2

我个人更喜欢pushState,因为它可以制作更好看的网址,我认为这对用户体验很重要。

如果您想使用pushState,但不希望旧版浏览器支持出现问题,则可以使用history.pushState并使用history.js polyfill作为散列回退。

+1

您的用户体验由多数用户甚至没有注意到的#决定? – Pascal 2016-07-16 15:18:57

2

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

因此,location.hash并没有死亡,事实上它会持续很长很长的时间。

一个很好的使用方法是使用支持pushState的lib,但也可以优雅地降级到使用location.hash
- https://github.com/browserstate/history.js

而且location.hash仍然是有用的跳转到命名锚。 pushState将在构建Web应用程序方面提供巨大帮助。我期待着使用它。

1

这是一个相当古老的问题(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检索,从未由服务器生成)。在这种情况下,如果您使用pushState over hash URL,则需要处理浏览器中的URL不是真实URL的情况。我会说明。

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

在这一点上,浏览器栏包含真正的链接到你的应用程序,将用户带到他们目前看到了同样的观点:主页。现在他们点击一个链接,将他们带到一个显示某个活动细节的“页面”。此时,您想更新位置栏以指示状态更改。你要么使用哈希URL和您的地址栏看起来像http://mysite/mainpage#charts/1或使用pushState的,它欺骗成为http://mysite/mainpage/charts/1

如果您使用pushState的,这是不是一个真正的链接。通过浏览器的前进/后退按钮导航将工作的伟大,并且用户将在主页转到详细页都在地址栏中,并在应用程序(假设你正确处理状态的改变),但如果用户的书签此链接或者复制和粘贴链接以共享它,将需要额外的服务器端voodoo。

您将需要请求重定向到/炫魅/图表/ 1 /炫魅然后用JS来解决实际的URL和执行预期的状态变化的操作。服务器重定向是绝对必需的。如果没有可编写脚本的http服务器,您无法在AWS或本地磁盘上托管此页面。

现在,如果你使用的哈希的网址,您的网址,用户将看到和互动与本来http://mysite/mainpage#/charts/1,这是一个有效的,真正的网址。浏览器明白,只有一个页面,以及用户是否复制和粘贴的链接或书签它,你只需要处理JavaScript中的散列状态,并且不需要任何服务器端魔法使事情的工作。

似乎没有人提到pushState和哈希链接不是相互排斥的。 pushState的只是操纵浏览器的位置,是对用户可见和现代浏览器中实现可靠的前进/后退导航的API。它没有提到你的URL方案应该是什么样子。

在2017年,谷歌和几乎所有其他的JS-能够BOT了解哈希URL和遍历他们就好了。 Google希望你使用#!可憎的最大化目的,但即使你不这样做,你的网站可以通航就好了。

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

+0

我不确定你最后一句话的意思:你是否建议用location.hash替换URL,然后用pushState再次执行?这将如何帮助?从我所了解的pushState的主要问题是书签,但如果我们这样做,我们不会结束带书签的URL,无论如何需要重定向魔术?顺便说一句,非常清楚和信息丰富,试图让所有这些信息感觉就像编写一个难题,在这里你真的触及几乎所有与讨论有关的,谢谢 – 2017-09-08 13:17:46

+0

@FabioLolli关于最后一句话 - 在我的应用程序中,我有时会发现自己通过'pushState'和'replaceState'操作位置哈希。例如,最近的一个应用程序在按键上执行搜索。此搜索应更新用于书签/转发等的URL,但您不希望每个按键都用新条目填满历史堆栈(就像操作'location.hash'一样)。相反,我在输入时使用'replaceState',然后在一些防反跳超时之后,或者如果有必要,按回车键执行'pushState'。 – ijmacd 2017-10-23 03:52:23

+0

其实,截至2015年10月,Google不希望您使用#!. https://webmasters.googleblog.com/2015/10/deprecating-our-ajax-crawling-scheme.html – javajosh 2017-10-31 18:59:08