javascript 多合一位置/哈希历史管理库
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11427258/
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
All-in-one location/hashchange history management library
提问by user123444555621
First of all, I know there's libraries that provide polyfills for location.pushState
/popState
(History.js, Hash.js, jQuery hashchange), so please don't just link to those.
首先,我知道有一些库为location.pushState
/ popState
(History.js、Hash.js、jQuery hashchange)提供polyfill,所以请不要只链接到这些库。
I need a more powerful library to achieve the following in a RIA:
我需要一个更强大的库来在 RIA 中实现以下目标:
- User clicks a link
- library is notified and loads context via Ajax (no complete reload!)
- All
<a>
elements are leveraged with a click handler that- prevents page reloads in 2. (
preventDefault
) and - calls
location.pushState
instead / sets location.hashfor older browsers
- prevents page reloads in 2. (
- loaded content is inserted in page and replaces current content
- Continue with 1.
- 用户点击链接
- 通过 Ajax 通知库并加载上下文(没有完全重新加载!)
- 所有
<a>
元素都通过一个点击处理程序来利用- 防止页面重新加载 2. (
preventDefault
) 和 location.pushState
改为调用/为旧浏览器设置location.hash
- 防止页面重新加载 2. (
- 加载的内容插入页面并替换当前内容
- 继续 1。
Also, previously loaded content should be restored as the user navigates back.
此外,当用户返回时,应恢复先前加载的内容。
As an example, klick through Google+in Internet Explorer <10 and any other browser.
例如,在 Internet Explorer <10 和任何其他浏览器中点击Google+。
Is there anything that comes even close? I need support for IE8, FF10, Safari 5 and Chrome 18. Also, it should have a permissive license like MIT or Apache.
有什么可以接近的吗?我需要支持 IE8、FF10、Safari 5 和 Chrome 18。此外,它应该有像 MIT 或 Apache 这样的宽松许可证。
回答by Geert-Jan
I believe Sammy.js ( http://sammyjs.org) (MIT-licenced) has the best focus on what you want to do, with its 2 main pillars being:
我相信 Sammy.js ( http://sammyjs.org) (MIT- licenced ) 最专注于你想做的事情,它的两个主要支柱是:
- Routes
- Events
- 路线
- 活动
I could quote from the docs but it's pretty straightforward:
我可以从文档中引用,但它非常简单:
setup clientside routes that relate to stuff to be done, e.g: update the view through ajax
link events to call routes, e.g: call the route above when I click an link. (You would have to make sure e.preventDefault is called in the defined event I believe, since this is an app decision really, so that can't be abstracted away by any library that you're going to use imho)
设置与要完成的事情相关的客户端路由,例如:通过 ajax 更新视图
链接事件来调用路由,例如:当我点击一个链接时调用上面的路由。(您必须确保在我相信的已定义事件中调用 e.preventDefault,因为这确实是一个应用程序决定,因此您将无法使用 imho 的任何库将其抽象化)
Some relevant docs
一些相关文档
Example for a route: (from http://sammyjs.org/docs/tutorials/json_store_1)
路线示例:(来自http://sammyjs.org/docs/tutorials/json_store_1)
this.get('#/', function(context) {
$.ajax({
url: 'data/items.json',
dataType: 'json',
success: function(items) {
$.each(items, function(i, item) {
context.log(item.title, '-', item.artist);
});
}
});
});
Or something like
或者类似的东西
this.get('#/', function(context) {
context.app.swap(''); ///the 'swap' here indicates a cleaning of the view
//before partials are loaded, effectively rerendering the entire screen. NOt doing the swap enables you to do infinite-scrolling / appending style, etc.
// ...
});
Of course other clientside MVC-frameworks could be an option too, which take away even more plumbing, but might be overkill in this situation.
当然,其他客户端 MVC 框架也可能是一种选择,这会消除更多管道,但在这种情况下可能会过大。
a pretty good (and still fairly recent) comparison:
一个相当不错的(而且仍然是最近的)比较:
http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/( I use Spine.js myself ) .
http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/(我自己使用 Spine.js)。
Lastly, I thought it might be useful to include an answer I've written a while ago that goes into detail to the whole best-practice (as I see it) in client-side refreshes, etc. Perhaps you find it useful:
最后,我认为包含我不久前写的一个答案可能会很有用,该答案详细介绍了客户端刷新等中的整个最佳实践(如我所见)。也许您觉得它很有用:
回答by Sujay
I currently use PathJSin one of my applications. It has been the best decision that i have made. For your particular usecase take a look at HTML5 Example.
我目前在我的一个应用程序中使用PathJS。这是我做过的最好的决定。对于您的特定用例,请查看HTML5 示例。
The piece of code that that makes the example work (from the source):
使示例工作的代码片段(来自源代码):
<script type="text/javascript">
// This example makes use of the jQuery library.
// You can use any methods as actions in PathJS. You can define them as I do below,
// assign them to variables, or use anonymous functions. The choice is yours.
function notFound(){
$("#output .content").html("404 Not Found");
$("#output .content").addClass("error");
}
function setPageBackground(){
$("#output .content").removeClass("error");
}
// Here we define our routes. You'll notice that I only define three routes, even
// though there are four links. Each route has an action assigned to it (via the
// `to` method, as well as an `enter` method. The `enter` method is called before
// the route is performed, which allows you to do any setup you need (changes classes,
// performing AJAX calls, adding animations, etc.
Path.map("/users").to(function(){
$("#output .content").html("Users");
}).enter(setPageBackground);
Path.map("/about").to(function(){
$("#output .content").html("About");
}).enter(setPageBackground);
Path.map("/contact").to(function(){
$("#output .content").html("Contact");
}).enter(setPageBackground);
// The `Path.rescue()` method takes a function as an argument, and will be called when
// a route is activated that you have not yet defined an action for. On this example
// page, you'll notice there is no defined route for the "Unicorns!?" link. Since no
// route is defined, it calls this method instead.
Path.rescue(notFound);
$(document).ready(function(){
// This line is used to start the HTML5 PathJS listener. This will modify the
// `window.onpopstate` method accordingly, check that HTML5 is supported, and
// fall back to hashtags if you tell it to. Calling it with no arguments will
// cause it to do nothing if HTML5 is not supported
Path.history.listen();
// If you would like it to gracefully fallback to Hashtags in the event that HTML5
// isn't supported, just pass `true` into the method.
// Path.history.listen(true);
$("a").click(function(event){
event.preventDefault();
// To make use of the HTML5 History API, you need to tell your click events to
// add to the history stack by calling the `Path.history.pushState` method. This
// method is analogous to the regular `window.history.pushState` method, but
// wraps calls to it around the PathJS dispatched. Conveniently, you'll still have
// access to any state data you assign to it as if you had manually set it via
// the standard methods.
Path.history.pushState({}, "", $(this).attr("href"));
});
});
</script>
PathJS has some of the most wanted features of a routing library:
PathJS 有一些最需要的路由库特性:
- Lightweight
- Supports the HTML5 History API, the 'onhashchange' method, and graceful degredation
- Supports root routes, rescue methods, paramaterized routes, optional route components (dynamic routes), and Aspect Oriented Programming
- Well Tested (tests available in the ./tests directory)
- Compatible with all major browsers (Tested on Firefox 3.6, Firefox 4.0, Firefox 5.0, Chrome 9, Opera 11, IE7, IE8, IE9)
- Independant of all third party libraries, but plays nice with all of them
- 轻的
- 支持 HTML5 History API、'onhashchange' 方法和优雅降级
- 支持根路由、救援方法、参数化路由、可选路由组件(动态路由)和面向切面编程
- 测试良好(测试在 ./tests 目录中可用)
- 兼容所有主流浏览器(在 Firefox 3.6、Firefox 4.0、Firefox 5.0、Chrome 9、Opera 11、IE7、IE8、IE9 上测试)
- 独立于所有第三方库,但与所有第三方库都很好
I found the last too points most attractive. You can find them here
我发现最后一点最有吸引力。你可以在这里找到它们
I hope you find this useful.
希望这个对你有帮助。
回答by Max Girkens
i'd like to suggest a combination of
我想建议组合
crossroads.js as a router http://millermedeiros.github.com/crossroads.js/
crossroads.js 作为路由器 http://millermedeiros.github.com/crossroads.js/
and hasher for handling browser history and hash urls (w/ plenty of fallback solutions): https://github.com/millermedeiros/hasher/(based on http://millermedeiros.github.com/js-signals/)
和用于处理浏览器历史记录和哈希 URL 的 hasher(带有大量后备解决方案):https: //github.com/millermedeiros/hasher/(基于http://millermedeiros.github.com/js-signals/)
This will still require a few lines of code (to load ajax content etc.), but give you loads and loads of other possibilities when handling a route.
这仍然需要几行代码(加载 ajax 内容等),但在处理路由时会给你带来负载和其他可能性的负载。
Here's an example using jQuery (none of the above libraries require jQuery, i'm just lazy...)
这是一个使用 jQuery 的示例(以上库都不需要 jQuery,我只是懒惰......)
http://fiddle.jshell.net/Fe5Kz/2/show/light
http://fiddle.jshell.net/Fe5Kz/2/show/light
HTML
HTML
<ul id="menu">
<li>
<a href="foo">foo</a>
</li>
<li>
<a href="bar/baz">bar/baz</a>
</li>
</ul>
<div id="content"></div>
JS
JS
//register routes
crossroads.addRoute('foo', function() {
$('#content').html('this could be ajax loaded content or whatever');
});
crossroads.addRoute('bar/{baz}', function(baz) {
//maybe do something with the parameter ...
//$('#content').load('ajax_url?baz='+baz, function(){
// $('#content').html('bar route called with parameter ' + baz);
//});
$('#content').html('bar route called with parameter ' + baz);
});
//setup hash handling
function parseHash(newHash, oldHash) {
crossroads.parse(newHash);
}
hasher.initialized.add(parseHash);
hasher.changed.add(parseHash);
hasher.init();
//add click listener to menu items
$('#menu li a').on('click', function(e) {
e.preventDefault();
$('#menu a').removeClass('active');
$(this).addClass('active');
hasher.setHash($(this).attr('href'));
});?
回答by sellmeadog
Have you looked at the BigShelf sample SPA (Single Page Application)from Microsoft? It sounds like it covers how to achieve most of what you're asking.
您是否看过Microsoft的BigShelf 示例 SPA(单页应用程序)?听起来它涵盖了如何实现您所要求的大部分内容。
It makes use of History.js, a custom wrapper object to easily control navigation called NavHistory and Knockout.jsfor click handling.
它使用 History.js,这是一个自定义包装器对象,可以轻松控制称为 NavHistory 的导航和用于单击处理的Knockout.js。
Here's an extremely abbreviated workflow of how this works: first you'll need to initialize a NavHistory
object which wraps history.js and registers a callback which executes when there is a push state or hash change:
这是一个极其简化的工作流程:首先,您需要初始化一个NavHistory
对象,该对象包装 history.js 并注册一个回调,该回调在推送状态或哈希更改时执行:
var nav = new NavHistory({
params: { page: 1, filter: "all", ... etc ... },
onNavigate: function (navEntry) {
// Respond to the incoming sort/page/filter parameters
// by updating booksDataSource and re-querying the server
}
});
Next, you'll define one or more Knockout.js view models with commands that can be bound to links buttons, etc:
接下来,您将使用可以绑定到链接按钮等的命令定义一个或多个 Knockout.js 视图模型:
var ViewModel = function (nav) {
this.search = function () {
nav.navigate({ page: 2, filter: '', ... }); // JSON object matching the NavHistory params
};
}
Finally, in your markup, you'll use Knockout.js to bind your commands to various elements:
最后,在您的标记中,您将使用 Knockout.js 将您的命令绑定到各种元素:
<a data-bind="click: search">...</a>
The linked resources are much more detailed in explaining how all of this works. Unfortunately, it's not a single framework like you're seeking, but you'd be surprised how easy it is to get this working.
链接的资源更详细地解释了所有这些是如何工作的。不幸的是,它不像您正在寻找的那样是一个单一的框架,但是您会惊讶地发现它是多么容易实现。
One more thing, following the BigShelf example, the site I'm building is fully cross-browser compatible, IE6+, Firefox, Safari (mobile and desktop) and Chrome (mobile and desktop).
还有一件事,按照 BigShelf 示例,我正在构建的站点完全跨浏览器兼容,IE6+、Firefox、Safari(移动和桌面)和 Chrome(移动和桌面)。
回答by arttronics
The AjaxTCR Library
seems to cover all bases and contains robust methods that I haven't seen before. It's released under a BSD License (Open Source Initiative).
在AjaxTCR Library
似乎涵盖所有基地,并包含稳健的方法,我以前从未见过的。它是在 BSD 许可证(开源计划)下发布的。
For example, here are five AjaxTCR.history();
methods:
例如,这里有五种AjaxTCR.history();
方法:
init(onStateChangeCallback, initState);
addToHistory(id, data, title, url, options);
getAll();
getPosition();
enableBackGuard(message, immediate);
init(onStateChangeCallback, initState);
addToHistory(id, data, title, url, options);
得到所有();
获取位置();
enableBackGuard(消息,立即);
The above addToHistory();
has enough parameters to allow for deep hash-linking in websites.
上面addToHistory();
有足够的参数来允许在网站中进行深度哈希链接。
More eye-candy of .com.cookie(), .storage(), and .template()provides more than enough methods to handle any session datarequirements.
更养眼.com.cookie() ,。存储() ,和.template()提供了足够多的方法来处理任何会话数据的要求。
The well documented AjaxTCR API webpagehas a plethora of information with downloadable doc's to boot!
有据可查的AjaxTCR API 网页提供了大量信息以及可下载的文档来引导!
Status Update:
That website also has an Examples Webpage Sectionincluding downloadable .zip fileswith ready to use Front End(Client) and Back End(Server) project files.
状态更新:
该网站还有一个示例网页部分,包括可下载的.zip 文件,其中包含可立即使用的前端(客户端)和后端(服务器)项目文件。
Notably are the following ready-to-useexamples:
One-way Cookie
HttpOnly Cookies
History Stealing
History Explorer
值得注意的是以下即用型示例:
One-way Cookie
HttpOnly Cookies
History Stealing
History Explorer
There are quite a bit other examples that rounds out the process to use many of their API methods, making any small learning curve faster to complete.
还有很多其他示例可以完善使用他们的许多 API 方法的过程,从而可以更快地完成任何小的学习曲线。
回答by Eliran Malka
Several suggestions
几点建议
- ExtJs, see their History Example, and here are the docs.
- YUI Browser History Manager.
- jQuery BBQseem to provide a more advanced feature-set over jQuery.hashcode.
- ReallySimpleHistorymay also be of help, though it's quite old and possibly outdated.
- ExtJs,请参阅他们的历史示例,这里是文档。
- YUI 浏览器历史记录管理器。
- jQuery BBQ似乎提供了比 jQuery.hashcode 更高级的功能集。
- RealSimpleHistory也可能有帮助,尽管它已经很旧并且可能已经过时了。
Note:ExtJs History has been extended to optimize duplicate (redundant) calls to add()
.
注意:ExtJs 历史已经扩展到优化对add()
.
回答by LessQuesar
PJAX is the process you're describing.
PJAX 是您所描述的过程。
The more advanced pjax techniques will even start to preload the content, when the user hovers over the link.
当用户将鼠标悬停在链接上时,更高级的 pjax 技术甚至会开始预加载内容。
This is a good pjax library. https://github.com/MoOx/pjax
这是一个很好的 pjax 库。 https://github.com/MoOx/pjax
You mark the containers which need will be updated on the subsequent requests:
您标记需要将在后续请求中更新的容器:
new Pjax({ selectors: ["title", ".my-Header", ".my-Content", ".my-Sidebar"] })
So in the above, only the title
, the .my-header
, .my-content
, and .my-sidebar
will be replaced with the content from the ajax call.
所以在上面,只有title
, .my-header
, .my-content
, 和.my-sidebar
会被 ajax 调用的内容替换。
Somethings to look out for
需要注意的事项
Pay attention to how your JS loads and detects when the page is ready. The javascript will not reload on new pages. Also pay attention to when any analytics calls get called, for the same reason.
注意您的 JS 如何加载和检测页面何时准备就绪。javascript 不会在新页面上重新加载。出于同样的原因,还要注意何时调用任何分析调用。