使用HTML5历史记录API的好教程(Pushstate?)


168

我正在研究使用HTML5历史记录API解决与AJAX加载的内容的深层链接问题,但我正在努力下手。有谁知道任何好的资源吗?

我想使用此方法,因为这似乎是允许发送那些链接可能未打开JS的可能性的好方法。当使用JS的人向不使用JS的人发送链接时,许多解决方案都会失败。

我的初步研究似乎指向JS中的History API和pushState方法。

http://html5demos.com/history

Answers:


181

要获得出色的教程,您仅需要有关此功能的Mozilla开发人员网络页面:https : //developer.mozilla.org/zh/DOM/Manipulating_the_browser_history

不幸的是,HTML5历史API在所有HTML5浏览器中都以不同的方式实现(使其不一致和错误),并且没有HTML4浏览器的后备功能。幸运的是,History.js为HTML5浏览器提供了交叉兼容性(确保所有HTML5浏览器都能按预期运行),还可以选择为HTML4浏览器提供哈希回退(包括对数据,标题,pushState和replaceState功能的维护支持)。

您可以在此处阅读有关History.js的更多信息:https : //github.com/browserstate/history.js

有关Hashbangs VS哈希VS HTML5历史API的文章,请参见此处:https : //github.com/browserstate/history.js/wiki/Intelligent-State-Handling


25
无耻的自插。优秀的帖子和插件。:)
Purag 2012年


28

使用HTML5 pushstate时请记住,如果用户复制或添加书签并加深访问,然后再次访问它,那将是直接服务器命中,它将显示404,因此您需要为此做好准备,即使pushstate js库也无济于事您。最简单的解决方案是向Nginx或Apache服务器添加重写规则,如下所示:

Apache(如果使用的是vhost,则在您的vhost中):

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
 </IfModule>

Nginx的

rewrite ^(.+)$ /index.html last;

那才是真正的答案。Balupton的History.js Wiki / tutorials等上没有此内容。事实上,History.js不使用哈希,因此您需要使用.htaccess重定向!
2012年

13
理想情况下,您的服务器/应用应适当地响应路由,而无需进行此重写。
sholsinger

同意,但对于许多现代JavaScript框架(如Backbone.js,Spine,Ember等)除外。这些本质上都是“一页” JavaScript应用程序。可以设计出一种为SEO等提供写后端模板的解决方案,但与此同时这将是必要的。
莫维斯·莱德福德

*对。我写这个在这里详细:readystate4.com/2012/05/17/...
Mauvis莱德福德

6

HTML5规范的历史是古怪。

history.pushState()本身不会调度popstate事件或加载新页面。这只是为了将国家推入历史。这是单页应用程序的“撤消”功能。您必须手动调度popstate事件或使用history.go()导航到新状态。这个想法是路由器可以监听popstate事件并为您导航。

注意事项:

  • history.pushState()并且history.replaceState()不要调度popstate事件。
  • history.back()history.forward()以及浏览器的后退和前进按钮会调度popstate事件。
  • history.go()history.go(0)重新加载整个页面,并且不调度popstate事件。
  • history.go(-1)(后1页)和history.go(1)(前1页)进行调度popstate事件。

您可以像这样使用历史记录API推送新状态并调度popstate事件。

history.pushState({message:'New State!'}, 'New Title', '/link'); window.dispatchEvent(new PopStateEvent('popstate', { bubbles: false, cancelable: false, state: history.state }));

然后popstate使用路由器监听事件。


1
仅仅是我,还是new PopStateEvent(...)在IE11 中似乎不起作用?有没有人知道的解决方法?
David Alan Hjelle

看起来IE 11需要以下内容: var pop_state_event = document.createEvent('Event'); pop_state_event.initEvent('popstate', true, true); window.dispatchEvent(pop_state_event);
David Alan Hjelle

4

您可以尝试Davis.js,它可以在可用时使用pushState在JavaScript中进行路由,而如果没有JavaScript,它可以让服务器端代码处理请求。



2

您可能想看看这个jQuery插件。他们的网站上有很多示例。http://www.asual.com/jquery/address/


同样,当关闭JS时,此解决方案似乎失败。我认为历史记录API具有与modrewrite结合使用的功能,因此始终总是由服务器在第一实例中处理链接,而无需从JS层重定向。
轻度绒毛,2010年

使用modrewrite,您走在正确的轨道上。管理历史API和在用户没有JS时进行处理的解决方案实际上是两件事。如果没有JS,则必须使用标准的href和服务器响应来处理用户。如果用户的浏览器支持,则可以将历史API构建为“具有一定的吸引力”。
内森·托滕

禁用JavaScript时,jQuery Address 1.3附带的Express和State示例都可以很好地工作。第二个使用PHP和mod_rewrite。
罗斯蒂斯拉夫(Rostislav)2010年

就是我的机智 我打算在不使用JS的情况下构建站点,添加AJAX元素,然后使用历史记录重写URL,从而保留深层链接。从理论上讲,这应该是一种比我所见过的方法更好的方法,因为该站点在任何阶段都将不依赖AJAX
Mild Fuzz 2010年

1
-1作为jQuery Address不是HTML5 State API的直接端口-不支持数据或标题以及replaceState。
balupton 2011年

2

我在History.js之上编写了一个非常简单的路由器抽象,称为StateRouter.js。它处于开发的早期阶段,但是我正在将其用作我正在编写的单页应用程序中的路由解决方案。像您一样,我发现History.js很难掌握,尤其是因为我对JavaScript还是很陌生,直到我了解到您确实确实需要(或应该拥有)路由抽象,因为它可以解决底层问题。问题。

这个简单的示例代码应演示其用法:

var router = new staterouter.Router();
// Configure routes
router
  .route('/', getHome)
  .route('/persons', getPersons)
  .route('/persons/:id', getPerson);
// Perform routing of the current state
router.perform();

为了说明其用法,我精心制作了一些小提琴


1
在Mac上的Chrome中,这种提琴不适用于我。引发错误。(未捕获的ReferenceError:未定义
staterouter

@DrewT谢谢,由于github.com上的更改,小提琴坏了,但是我已经解决了。
aknuds1 2014年

是的,现在正在工作,感谢您的快速回复。
DrewT

1

如果有jQuery,则可以使用jQuery BBQ


JS关闭似乎失败了。
轻度毛绒2010年

可能是这样-尚未研究。我认为所有基于js库的方法都会遇到这个问题。它们基于操纵url的哈希部分。
sprugman 2010年

1
这就是HTML5历史记录API的意义-它不会破坏任何内容
balupton 2011年

2
@MildFuzz计算机似乎在没有电源的情况下发生了故障!我认为您有一个ID-10-T错误...
Eric Hodonsky

1
具有讽刺意味的是,您是有过失的人
Mild
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.