一体化位置/ hashchange历史管理库

use*_*621 42 javascript cross-browser browser-history

首先,我知道有提供polyfills图书馆location.pushState/ popState(History.js,Hash.js,jQuery的hashchange),所以请不要只是链接到这些.

我需要一个更强大的库来实现RIA中的以下功能:

  1. 用户单击链接
  2. 库通知并通过Ajax加载上下文(没有完全重新加载!)
  3. <a>利用点击处理程序利用所有元素
    • 防止2.(preventDefault)和中的页面重新加载
    • 为旧版浏览器调用location.pushState/设置location.hash
  4. 已加载的内容将插入页面并替换当前内容
  5. 继续1.

此外,应在用户导航回来时恢复以前加载的内容.

例如,在Internet Explorer <10和任何其他浏览器中点击Google+.

有什么东西可以接近吗?我需要支持IE8,FF10,Safari 5和Chrome 18.此外,它应该拥有像MIT或Apache这样的许可许可.

Gee*_*Jan 21

我相信Sammy.js(http://sammyjs.org)(麻省理工学院授权)最关注你想做的事情,它的两个主要支柱是:

  1. 路线
  2. 活动

我可以引用文档,但它非常简单:

  • 设置与要完成的事物相关的客户端路由,例如:通过ajax更新视图

  • 将事件链接到呼叫路由,例如:单击链接时调用上面的路由.(您必须确保在我认为的已定义事件中调用e.preventDefault,因为这确实是一个应用程序决策,因此任何您将要使用的库都无法将其抽象出来)

一些相关的文档

路线示例:(来自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);
        });
      }
    });
  });
Run Code Online (Sandbox Code Playgroud)

或类似的东西

 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. 
     // ...
   });
Run Code Online (Sandbox Code Playgroud)

当然,其他客户端MVC框架也可以是一个选项,它可以带走更多的管道,但在这种情况下可能会过度杀伤.

一个相当不错(但仍然相当近)的比较:

http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/ (我自己使用Spine.js).

最后,我认为包含我刚才写的答案可能是有用的,这个答案会详细介绍客户端刷新等中的最佳实践(如我所见).也许您觉得它很有用:

可访问性和所有这些JavaScript框架

  • 我****1**来补偿那些人.现在,Upvotes是公平的.话虽如此,看起来你将获得**最佳投票**的1/2,因为OP未能手动奖励全部**+ 500**.干杯! (2认同)

Suj*_*jay 9

我目前在我的一个应用程序中使用PathJS.这是我做出的最佳决定.对于您的特定用例,请查看HTML5示例.

使示例工作的代码片段(来自源代码):

<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>
Run Code Online (Sandbox Code Playgroud)

PathJS具有路由库的一些最需要的功能:

  • 轻量级
  • 支持HTML5 History API,'onhashchange'方法和优雅降级
  • 支持根路由,救援方法,参数化路由,可选路由组件(动态路由)和面向方面编程
  • 测试良好(./tests目录中提供的测试)
  • 兼容所有主流浏览器(在Firefox 3.6,Firefox 4.0,Firefox 5.0,Chrome 9,Opera 11,IE7,IE8,IE9上测试)
  • 独立于所有第三方图书馆,但与所有这些图书馆一起玩得很好

我发现最后一点太有吸引力了.你可以在这里找到它们

希望这个对你有帮助.


Max*_*ens 8

我想建议一个组合

crossroads.js作为路由器 http://millermedeiros.github.com/crossroads.js/

和浏览器历史记录和哈希网址(有大量的后备解决方案):https: //github.com/millermedeiros/hasher/ (基于http://millermedeiros.github.com/js-signals/)

这仍然需要几行代码(以加载ajax内容等),但在处理路径时为您提供其他可能性的负载和负载.

这是一个使用jQuery的例子(上面的库都不需要jQuery,我只是懒惰...)

http://fiddle.jshell.net/Fe5Kz/2/show/light

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>
Run Code Online (Sandbox Code Playgroud)

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'));
});?
Run Code Online (Sandbox Code Playgroud)


sel*_*dog 5

您是否查看过Microsoft 的BigShelf示例SPA(单页应用程序)?听起来它涵盖了如何实现您所要求的大部分内容.

它利用History.js,一个自定义包装器对象来轻松控制名为NavHistory和Knockout.js的导航,以便进行点击处理.

下面是一个极其简短的工作流程:首先,您需要初始化一个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
    }
});
Run Code Online (Sandbox Code Playgroud)

接下来,您将使用可绑定到链接按钮等的命令定义一个或多个Knockout.js视图模型:

var ViewModel = function (nav) {
  this.search = function () {
    nav.navigate({ page: 2, filter: '', ... }); // JSON object matching the NavHistory params
  };
}
Run Code Online (Sandbox Code Playgroud)

最后,在您的标记中,您将使用Knockout.js将命令绑定到各种元素:

<a data-bind="click: search">...</a>
Run Code Online (Sandbox Code Playgroud)

链接的资源在解释所有这些工作原理时要详细得多.不幸的是,它不像你正在寻找的单一框架,但你会惊讶于它是如何容易实现的.

还有一件事,按照BigShelf的例子,我正在构建的网站完全兼容跨浏览器,IE6 +,Firefox,Safari(移动和桌面)以及Chrome(移动和桌面).


Eli*_*lka 3

几点建议

注意: ExtJs 历史记录已扩展以优化对add().

  • 虽然 ExtJS 是一个很棒的框架,但它 1)如果仅用于所讨论的问题,那就有点矫枉过正了;2) 尚未实现新的 History API;3)相当原始,没有路由框架+像你提到的那样的怪癖(关于冗余调用) (2认同)