Memo
尽管即使在现代浏览器中,状态处理方面仍存在一些合法的 bug 和差异,但如今它们已经足够小,你可以直接使用原生 HTML5 History API。如果你打算支持旧版浏览器,那么 History.js 是你的选择。
此通知在此,因为 History.js 未获得足够的资金来维护,因此它仅以遗留状态存在于旧版浏览器中。也许它仍然适用于现代浏览器,但它确实需要维护。维护非常困难,因为该库需要在 HTML5 和 HTML4 模式下进行手动测试,并且针对每个适配器,以及每个浏览器。这意味着需要由人类运行 2^(# of adapters)^(# of browsers and their versions) 个测试。测试需要由人类运行,因为某些故障需要浏览器交互,例如从测试套件导航到不同的域再返回,或点击物理后退按钮,或检查物理后退按钮是否实际有效。这需要大量时间。
尽管 History.js 是当下最流行的 JavaScript 库之一,并且在其鼎盛时期曾被拥有数百万用户的公司所使用——但经济现实和公司惯例似乎表明,公司更倾向于 fork 自己的内部版本,并让自家开发者在本地进行修复,而不是资助开源维护者(尽管资助维护者能让包括他们自己在内的所有人都受益,且成本更低)——但不行,那需要太多层级的公司审批,而这些审批者并不理解其中的必要性。
因此,如果你是一名开源开发者,我建议只从事那些由你自己的咨询业务或你自己的公司付费支持的开源项目(例如每一个成功的开源项目)。否则,当它们变得流行时,你最好希望它们易于维护和测试,否则维护成本将高于维护者的空闲时间。
话虽如此,此仓库仍然存在,用于存档目的、支持遗留浏览器,以及作为无政府主义式的问题与 fork 维护中心。
祝好, Benjamin Lupton,Bevry 创始人,History.js 创造者
欢迎使用 History.js
v1.8b2,2013 年 6 月 22 日
新闻
- 22/06/2013: v1.8 的 Beta 2 版本已发布。修复了问题并包含未压缩的捆绑文件。
- 31/05/2013: v1.8 的 Beta 1 版本已发布。修复了问题。
- 14/02/2013: v1.8 的 Alpha 4 版本已发布。修复了问题。
- 05/02/2013: v1.8 的 Alpha 3 版本已发布。更新了测试。
- 21/01/2013: v1.8 的 Alpha 2 版本已发布。修正了 statechange 行为。
- 19/01/2013: v1.8 的 Alpha 1 版本已发布。开始对 balupton 的旧问题进行分类。
历史
请参阅 HISTORY.md 文件以获取功能、变更、已解决问题和 bug 的详细列表
参与
如果某些功能无法正常工作或存在特定浏览器的 bug,请创建一个 issue。我会尽快尝试修复。如果您有不错的解决方案,请向我发送 Pull requests!我还将审查 balupton 仓库中的旧 issue 并尝试解决它们。
目标
- 尽可能遵循 HTML5 History API
- 为所有 HTML5 浏览器提供跨兼容体验(它们对 HTML5 History API 的实现略有不同,导致行为差异甚至偶尔出现 bug - History.js 修复了这些问题,确保在所有 HTML5 浏览器中体验一致、符合预期且出色)
- 使用 hash-fallback 为所有 HTML4 浏览器提供向后兼容体验(包括继续支持 HTML5 History API 的
data、title、pushState和replaceState),并可选择 移除 HTML4 支持(如果它不适合你的应用程序 - 为 HTML4 状态到 HTML5 状态提供向前兼容体验(因此,如果通过 HTML5 浏览器访问使用 hash-fallback 的 URL,它会自然地转换为对应的非哈希 URL 等价形式)
- 通过适配器尽可能支持多种 javascript 框架;特别是 Dojo、ExtJS、jQuery、MooTools、Right.js 和 Zepto。
快速安装
通过 Ajaxify 脚本
若要使用 HTML5 History API、History.js 和 jQuery 将整个网站 ajaxify,Ajaxify 脚本 就足够了。就是这么简单。
通过 Ajaxify 扩展
如果你无法访问服务器,或者只是想先试用 Ajaxify 脚本,你可以安装 History.js It! Google Chrome 扩展,以便在特定网站上通过 Ajaxify 试用 History.js,而无需在服务器上实际安装 History.js/Ajaxify。
通过 Ruby On Rails Gem
如果你正在使用 Rails,那么尝试 History.js 最简单的方式就是使用 Wiselinks gem。Wiselinks 将其集成到 Rails 应用程序中,并允许你通过三行代码开始使用 History.js。
直接安装
直接使用 History.js
(function(window,undefined){
// Bind to StateChange Event
History.Adapter.bind(window,'statechange',function(){ // Note: We are using statechange instead of popstate
var State = History.getState(); // Note: We are using History.getState() instead of event.state
});
// Change our States
History.pushState({state:1}, "State 1", "?state=1"); // logs {state:1}, "State 1", "?state=1"
History.pushState({state:2}, "State 2", "?state=2"); // logs {state:2}, "State 2", "?state=2"
History.replaceState({state:3}, "State 3", "?state=3"); // logs {state:3}, "State 3", "?state=3"
History.pushState(null, null, "?state=4"); // logs {}, '', "?state=4"
History.back(); // logs {state:3}, "State 3", "?state=3"
History.back(); // logs {state:1}, "State 1", "?state=1"
History.back(); // logs {}, "Home Page", "?"
History.go(2); // logs {state:3}, "State 3", "?state=3"
})(window);
上述操作在 HTML5 浏览器中会是什么样子?
- www.mysite.com
- www.mysite.com/?state=1
- www.mysite.com/?state=2
- www.mysite.com/?state=3
- www.mysite.com/?state=4
- www.mysite.com/?state=3
- www.mysite.com/?state=1
- www.mysite.com
- www.mysite.com/?state=3
注意:这些 URL 在 HTML4 浏览器和搜索引擎中也能正常工作。因此,无需使用 hashbang (
#!) fragment-identifier,正如谷歌所"推荐"的那样。
它们在 HTML4 浏览器中会是什么样子?
- www.mysite.com
- www.mysite.com/#?state=1&_suid=1
- www.mysite.com/#?state=2&_suid=2
- www.mysite.com/#?state=3&_suid=3
- www.mysite.com/#?state=4
- www.mysite.com/#?state=3&_suid=3
- www.mysite.com/#?state=1&_suid=1
- www.mysite.com
- www.mysite.com/#?state=3&_suid=3
注意 1:这些 URL 在 HTML5 浏览器中也能正常工作 - 我们使用
replaceState将这些 HTML4 状态转换为它们的 HTML5 等价形式,用户甚至不会注意到 :-)注意 2:这些 URL 在 IE6 中会自动进行 URL 编码,以防止某些特定于浏览器的 bug。
注意 3:对 HTML4 浏览器的支持(这种 hash 回退机制)是可选的 - 为什么支持 HTML4 浏览器可能基于我应用的使用场景而有好有坏
HTML4 状态中使用的 SUID 是怎么回事?
- SUIDs(State Unique Identifiers,状态唯一标识符)在我们使用
title和/或data于状态中时会被使用。添加 SUID 允许我们将特定状态与数据和标题关联起来,同时保持 URL 尽可能简单(别担心,这一切都经过测试,运行正常,而且比我所描述的更智能)。 - 如果你没有使用
title或data,那么我们甚至不会包含 SUID(因为不需要)——正如上面 State 4 所示 :-) - 我们还会缩小 URL,以确保使用最小的 URL。例如,我们会自动将
http://www.mysite.com/#http://www.mysite.com/projects/History.js调整为http://www.mysite.com/#/projects/History.js。(再次强调,经过测试,运行正常,且更智能)。 - 它适用于域名、子域名、子目录等——无论放在哪里都没关系。它很智能。
- Safari 5 也会在 URL 后附加一个 SUID,这完全是透明的,只是一个可见的副作用。这是为了修复 Safari 5 中的一个 bug 所必需的。
有可用的演示吗?
- 当然有,请下载并在浏览器中导航到演示目录 :-)
- 如果你想要比最终用户演示更冒险一点的东西,请在浏览器和编辑器中打开 tests 目录——它将震撼你的世界,并展示 History.js 支持的所有广泛用例。
下载与安装
-
包含 History.js
-
对于 Dojo v1.8+
<script src="http://www.yourwebsite.com/history.js/scripts/bundled/html4+html5/dojo.history.js"></script>
-
-
对于 ExtJs v1.8+
``` html <script src="http://www.yourwebsite.com/history.js/scripts/bundled/html4+html5/extjs.history.js"></script> ``` -
对于 jQuery v1.3+
``` html <script src="http://www.yourwebsite.com/history.js/scripts/bundled/html4+html5/jquery.history.js"></script> ``` -
适用于 Mootools v1.3+
``` html <script src="http://www.yourwebsite.com/history.js/scripts/bundled/html4+html5/mootools.history.js"></script> ``` -
适用于 Right.js v2.2+
``` html <script src="http://www.yourwebsite.com/history.js/scripts/bundled/html4+html5/right.history.js"></script> ``` -
适用于 Zepto v0.5+
``` html <script src="http://www.yourwebsite.com/history.js/scripts/bundled/html4+html5/zepto.history.js"></script> ``` -
其他所有内容
``` html <script src="http://www.yourwebsite.com/history.js/scripts/bundled/html4+html5/native.history.js"></script> ```
注意:如果你只想支持 HTML5 浏览器而不支持 HTML4 浏览器(即不支持 hash 回退),只需将 URL 中的
/html4+html5/部分更改为/html5/。参见 为什么支持 HTML4 浏览器可能基于我的应用用例而有利有弊
获取更新
- 关于 Commit RSS/Atom 更新:
- 你可以通过 GitHub Commit Atom Feed 进行订阅
- 关于 GitHub 新闻源更新:
- 你可以点击 History.js GitHub 项目页面 右上角的 "watch" 按钮
获取支持
-
History.js 由像你一样的人维护。如果你发现了一个 bug,请将其报告到 GitHub Issue Tracker。如果你修复了一个 bug,请提交一个 Pull Request 并将你的 fork 添加到 Network Wiki Page。
-
如果你希望获得付费支持和培训,或者有工作机会,请参阅 Network Wiki Page。如果你精通 History.js,请务必将你的详细信息也添加到该页面。
-
如果你的公司在项目中使用 History.js,并希望看到它发展壮大(更好的文档、bug 修复、升级、维护等),并且愿意成为企业赞助商,请发送电子邮件至 sponsor@bevry.me
-
如果你希望获得 History.js 的免费支持,请在 Stackoverflow 上 发布你的问题,并在提问时务必使用
history.js标签。 -
如果你创建了一个使用 History.js 的网站,或者知道这样一个网站,请务必将其添加到 Showcase Wiki Page。
-
如果你愿意为这个项目 +1 或点赞,请务必在推特上分享它,并点击其 Project Page 顶部的“watch”按钮。
-
其他任何内容,请参阅 History.js GitHub Wiki Site。
谢谢!每一份帮助都真的能带来改变!
浏览器:已测试并支持
HTML5 浏览器
- Firefox 4+
- Chrome 8+
- Opera 11.5+
- Safari 5.0+
- Safari iOS 4.3+
HTML4 浏览器
- IE 6, 7, 8, 9, (10)
- Firefox 3
- Opera 10, 11.0
- Safari 4
- Safari iOS 4.2, 4.1, 4.0, 3.2
暴露的 API
函数
状态
History.pushState(data,title,url)
向浏览器推送一个新状态;data可以为 null 或一个对象,title可以为 null 或一个字符串,url必须是一个字符串History.replaceState(data,title,url)
用新状态替换浏览器中的现有状态;data可以为 null 或一个对象,title可以为 null 或一个字符串,url必须是一个字符串History.getState()
获取浏览器的当前状态,返回一个包含data、title和url的对象History.getStateByIndex
通过索引获取状态History.getCurrentIndex
获取当前索引History.getHash()
获取浏览器的当前 hash
适配器
History.Adapter.bind(element,event,callback)
一个框架无关的事件绑定器,你可以使用它,也可以使用你框架的原生事件绑定器。History.Adapter.trigger(element,event)
一个框架无关的事件触发器,你可以使用它,也可以使用你框架的原生事件触发器。History.Adapter.onDomLoad(callback)
一个框架无关的 onDomLoad 绑定器,你可以使用它,也可以使用你框架的原生 onDomLoad 绑定器。
导航
History.back()
在历史记录中后退一次(等同于点击浏览器的后退按钮)History.forward()
在历史记录中前进一次(等同于点击浏览器的前进按钮)History.go(X)
如果 X 为负数,则在历史记录中后退 X 次;如果 X 为正数,则在历史记录中前进 X 次
Debug
History.log(...)
将消息记录到控制台、log 元素,如果这两者都不存在则回退到 alertHistory.debug(...)
与History.log相同,但仅在History.options.debug === true时运行
Options
History.options.hashChangeInterval
在执行 hashchange 检查之前,间隔时间应为多久History.options.safariPollInterval
在执行 safari 轮询检查之前,间隔时间应为多久History.options.doubleCheckInterval
在执行双重检查之前,间隔时间应为多久History.options.disableSuid
强制 History 不追加 suidHistory.options.storeInterval
在 store 调用之间应等待多久History.options.busyDelay
在 busy 事件之间应等待多久History.options.debug
如果为 true,将启用调试消息的记录History.options.initialTitle
初始状态的标题是什么History.options.html4Mode
如果为 true,将强制使用 HTMl4 模式(hashtags)History.options.delayInit
希望覆盖默认选项并手动调用 init。
Events
window.onstatechange
当页面状态发生变化时触发(不包括 hash 变化)window.onanchorchange
当页面锚点发生变化时触发(不包括状态 hash)
已知问题
- Opera 11 在高负载下无法创建历史记录条目(事件正常触发,只是历史记录事件失败)- 对此我们无能为力
- Mercury iOS 无法应用 URL 更改(哈希和 HTML5 History API 状态)- 对此我们无能为力
兼容性说明
-
History.js 解决了以下浏览器缺陷:
- HTML5 浏览器
- Chrome 8 在回溯到初始状态时,有时不包含正确的状态数据
- Safari 5、Safari iOS 4 以及 Firefox 3 和 4 在页面通过哈希加载时,不会触发
onhashchange事件 - 与其他浏览器不同,Safari 5 和 Safari iOS 4 在哈希发生变化时不会触发
onpopstate事件 - 一旦哈希被
replaceState调用替换,Safari 5 和 Safari iOS 4 无法返回到正确的状态 / bug report - 在繁忙条件下,Safari 5 和 Safari iOS 4 有时无法应用状态变更 / bug report
- 在 RC 版本之前的 Google Chrome 8、9、10 和 Firefox 4,在页面加载完成后总会触发一次
onpopstate/ change recommendation - Safari iOS 4.0、4.1、4.2 拥有可用的 HTML5 History API - 尽管浏览器实际的返回按钮不起作用,因此我们将它们视为 HTML4 浏览器
- 没有任何 HTML5 浏览器实际利用
pushState和replaceState调用中的title参数
- HTML4 浏览器
- 像 MSIE 6、7 和 Firefox 2 这样的旧浏览器没有
onhashchange事件 - MSIE 6 和 7 有时即使被指示应用哈希也不会应用(需要对应用函数进行第二次调用)
- 非 Opera 的 HTML4 浏览器在哈希不是
urlencoded时,有时不会应用该哈希
- 像 MSIE 6、7 和 Firefox 2 这样的旧浏览器没有
- 所有浏览器
- 一旦离开站点然后返回(包括页面刷新),状态数据和标题不会持久化
- 状态标题从未被应用到
document.title
- HTML5 浏览器
-
ReplaceState 功能在 HTML4 浏览器中通过丢弃被替换的状态来模拟,因此当访问被丢弃的状态时,会使用相应的
History.back()/History.forward()调用将其跳过 -
数据持久化和同步的工作方式如下:大约每隔一秒,状态的 SUID 和 URL 会在存储和本地会话之间进行同步。当新会话打开一个熟悉的状态(通过 SUID 或 URL)且在本地未找到时,它将尝试加载具有该信息的最后已知存储状态。
-
URL 将被最大程度地解转义,例如 URL
?key=a%20b%252c将变为?key=a b c。这是为了确保浏览器 URL 编码之间的一致性。 -
更改页面的哈希值会触发
onpopstate(这是预期/标准功能)。为了确保 HTML5 和 HTML4 浏览器之间的正确兼容性,已创建以下事件:window.onstatechange:这与onpopstate事件相同,但不会为传统锚点触发window.onanchorchange:这与onhashchange事件相同,但不会为状态触发
许可证
根据 New BSD License
版权所有 © 2014+ Bevry Pty Ltd us@bevry.me
版权所有 © 2011-2013 Benjamin Arthur Lupton b@lupton.cc
有关支持,请参阅 获取支持 部分。