跨浏览器使用jquery ajax历史记录的方法:使用window.history.pushState和备选方案

31

我想要使用jQuery和AJAX以跨浏览器的方式实现导航历史。我的方法是使用window.history.pushState,并在不支持window.history.pushState的浏览器中回退到哈希url /#!/url

例如:

<a href="/home">home</a>
<a href="/about">about</a>
<a href="/contact">contact</a>
在支持 window.history.pushState 的浏览器中,点击这些链接之一应该可以在不刷新页面的情况下更改地址为 http://domain.com/homehttp://domain.com/about 等等。当浏览器不支持 window.history.pushState 时,它应该使用片段标识符,即:http://domain.com/#!/homehttp://domain.com/#!/about

更新:根据这里的反馈,我已经实现了 Ajax SEOgit),它使用jQuery Address 来进行 HTML5 历史 API,对于旧版本浏览器则回退到 /#!/url


我在想,如果你需要支持不支持pushState的浏览器,为什么不在所有浏览器中都使用哈希URL方法呢?除了为了“正确性”之外,使用pushState有哪些优势可以弥补支持多种方法所带来的复杂性? - David Hammond
@DavidHammond,这就是 https://github.com/laukstein/ajax-seo 直接支持的内容。 - Binyamin
3个回答

22
// Assuming the path is retreived and stored in a variable 'path'

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

6

我一直在使用的一种具备回退哈希URL功能的东西:

History = History || {};
History.pathname = null;
History.previousHash = null;
History.hashCheckInterval = -1;
History.stack = [];
History.initialize = function () {
    if (History.supportsHistoryPushState()) {
        History.pathname = document.location.pathname;
        $(window).bind("popstate", History.onHistoryChanged);
    } else {
        History.hashCheckInterval = setInterval(History.onCheckHash, 200);
    }
};
History.supportsHistoryPushState = function () {
    return ("pushState" in window.history) && window.history.pushState !== null;
};
History.onCheckHash = function () {
    if (document.location.hash !== History.previousHash) {
        History.navigateToPath(document.location.hash.slice(1));
        History.previousHash = document.location.hash;
    }
};
History.pushState = function (url) {
    if (History.supportsHistoryPushState()) {
        window.history.pushState("", "", url);
    } else {
        History.previousHash = url;
        document.location.hash = url;
    }
    History.stack.push(url);
};
History.onHistoryChanged = function (event) {
    if (History.supportsHistoryPushState()) {
        if(History.pathname != document.location.pathname){
            History.pathname = null;
            History.navigateToPath(document.location.pathname);
        }
    }
};
History.navigateToPath = function(pathname) {
    History.pushState(pathname);

    // DO SOME HANDLING OF YOUR PATH HERE

};

您可以使用以下方式将单击事件绑定到此项上:
$(function(){
    $("a").click(function(){
        var href = $(this).attr('href');
        History.navigateToPath( href )
        return false;
    });
});

如果您需要对此示例进行更多解释,我很乐意听取意见。
编辑 请查看我的其他回答。

4

自从我的原始答案发布以来已经有一段时间了,我现在建议使用Backbone

一个实现可能是:

// First setup a router which will be the responder for URL changes:
var AppRouter = Backbone.Router.extend({

  routes: {
    "*path": "load_content"
  },

  load_content: function(path){
    $('#content').load('/' + path);
  }

});
var appRouter = new AppRouter;

// Then initialize Backbone's history
Backbone.history.start({pushState: true});

文档摘录:

如果您想在应用程序中使用HTML5 pushState支持,请使用Backbone.history.start({pushState: true})。如果您想使用pushState,但是有浏览器不支持原生的情况下,可以将{hashChange: false}添加到选项中,以使用完整页面刷新代替。

现在,每次调用Backbone.history.navigate时,AppRouter将执行将路径加载到#content div中的AJAX操作。

要处理所有带有AJAX的链接,可以使用以下内容:

$("a").on('click', function(event){
    event.preventDefault();
    Backbone.history.navigate( event.currentTarget.pathname, {trigger: true} )
});

注意 {trigger: true},它会触发路由中的处理程序被调用(否则只能通过URL更改触发)。

尝试示例代码:http://jsfiddle.net/koenpunt/pkAz7/1/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接