jquery - pushState() 和 popState() : manipulating browsers' history

标签 jquery html pushstate history.js popstate

我正在做一个小项目,我想在其中创建一个 Ajax 风格的网站。内容使用 jQuery 的 load() 加载.正如你们中的一些人所知,这样做的缺点是 URL 不会根据显示的内容相应地更改。要完成这项工作,您可以使用 pushState() .因为这个不支持跨浏览器,所以我用了插件history.js .

这工作得很好,但问题是我的后退和前进按钮没有正常工作,我不知道我做错了什么。 URL 正在正确更改,内容也是如此,但标题根本没有更改。标题是指显示为浏览器窗口(或选项卡)标题的内容。 IE。 <title>加载页面的名称或引用该页面的链接的标题属性(它们是相同的)。我认为这与我只调用我需要标题的页面部分这一事实有关(即通过将 #content 添加到 load() )。我仍然想要那个页面的标题。这是我到目前为止的测试用例。 (自 2013 年 12 月 28 日起不再可用。)jQuery 文件:

$(document).ready(function () {
    var firstLink = $("ul > li:first-child > a");
    var menuLink = $("ul > li > a");
    var firstLoadedHtml = firstLink.attr("href") + " #content";

    $("#sectionContainer").hide().load(firstLoadedHtml).fadeIn("fast");
    firstLink.addClass("active");   

    menuLink.click(function(e) {
        history.pushState(null, null, this.href);

        e.preventDefault();
        e.stopImmediatePropagation();

        var CurLink = $(this);
        var newLoadedHtml = CurLink.attr("href") + " #content";
        var oldSection = $(".contentPage");

        $("#sectionContainer").hide().load(newLoadedHtml).fadeIn("fast");
        menuLink.removeClass("active");
        CurLink.addClass("active");
    });

    $(window).bind('popstate', function() {
            var returnLocation = history.location || document.location;

            $('#sectionContainer').load(returnLocation + "#content");
    });
});

我还注意到,当返回到基本页面(即/sectionLoaderTest/)时,它会暂时空白,并且仅在一段时间后加载第一页的内容。有没有办法优化这个?

此外,我正在使用 jQuery 将事件类添加到已单击的链接。我怎样才能确保这会根据历史发生变化?以便在用户返回时突出显示正确的链接?

所以这三个问题是:

  1. 让标题在前进和后退时发挥作用
  2. 优化主页的加载时间
  3. 在前进和后退时修复事件类

欢迎大家帮忙!

注意 1:我想在 history.js 和我自己的脚本的基础上构建,因此继续支持 < HTML5浏览器。我更喜欢这个,因为 1. 我知道这必须起作用,只是出了点问题。 2. 如果我能看到一个人的解决方案并在我已经编写的脚本中实现它,而不是想出一个全新的脚本,这将节省时间。

注意2:赏金只会给予能够回答我所有问题(3)的人!

最佳答案

答案 1 - 让标题在前进和后退时发挥作用

据我了解,您想更改链接中的文档标题 html 已加载到 div 中。当您通过 jQuery .load 在 div 中加载文件时,您只是在其中的 ajax 请求之后插入完整的响应文本。所以所有不应该在 div 中的东西,比如 titlemeta 标签。但是,当前文档的标题 (http://bramvanroy.be/sectionLoaderTest/index.html) 是在 head< 内的 title 中定义的 标签而不是 div 内的 title 标签,所以这就是文档标题没有改变的原因。

那我该如何解决呢?

问得好,因为 div 元素中的 title 元素无效,大多数浏览器会删除它,因此您不能只使用它:

document.title = $("#sectionContainer title").text();

因为 title 元素可能不存在。

所以我们需要的是 jQuery .load 函数的直接响应。我可以通过向函数添加回调参数来获取它:

$("#sectionContainer")
    .hide()
    .load(newLoadedHtml, function(responseText) {
        document.title = $(responseText).filter("title").text();
    })
    .fadeIn("fast");

您可能不明白的是,为什么我使用.filter 而不是.find 函数。这是因为 jQuery 会从 html 中解析出 htmlheadbody 标记,但不会删除其中的子元素。

答案 2 - 优化主页的加载时间

文档正在从上到下加载。

所以首先应该加载 css、JavaScript 等,然后是主文档。 因为 jQuery 总是在执行之前等待文档,所以将所有 script 元素放在正文末尾之前并不是一个非常糟糕的主意,这样您的 HTML 就可以在之前加载。

顺便说一句,在所有内容都被缓存并且文档加载速度非常快之后,我第一次遇到这个问题。

答案3 - 修复前进后退时的active-class

我会说循环遍历 a 元素的 href 属性,并将其与来自 History.getState() 的数据进行比较。应该很容易。

您在代码中犯了一些错误 - 您的修正代码:

您将散列 #content 附加到所有 URL.. 它没有意义,它将再次被 jQuery 删除:https://github.com/jquery/jquery/blob/master/src/ajax.js#L617 (来自第 158、190、337、617 行 - rhash 在第 6 行)

$(document).ready(function () {
    var firstLink = $("ul > li:first-child > a");
    var menuLink = $("ul > li > a");
    var firstLoadedHtml = firstLink.attr("href");

    $("#sectionContainer").hide().load(firstLoadedHtml).fadeIn("fast");
    firstLink.addClass("active");   

    menuLink.click(function(e) {

        e.preventDefault();
        e.stopImmediatePropagation();

        var newLoadedHtml = $(this).attr("href");

        History.pushState(null, newLoadedHtml, newLoadedHtml);

        $("#sectionContainer")
            .hide()
            .load(newLoadedHtml, function(responseText) {
                document.title = $(responseText).filter("title").text();
            })
            .fadeIn("fast");
    });

    History.Adapter.bind(window, "statechange", function() {
        menuLink.removeClass("active");
        $("a[href='" + History.getState().title + "']").addClass("active");
        $('#sectionContainer').load(document.location.href, function(responseText) {
            document.title = $(responseText).filter("title").text();
        }); 
    });
});

关于jquery - pushState() 和 popState() : manipulating browsers' history,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10632483/

相关文章:

javascript - HTML 模板 - 不要两次编写相同的 html (couchdb)

jquery - jquery 新手 - 淡出对我不起作用

html - Polymer 1.0 中的核心支架元件

javascript - 如何使用仪表板在WordPress中插入iframe

javascript - 根据从 UI 中选择的时区过滤 php 中的日期

jquery - Internet Explorer 中的 History.js 哈希回退和 PushState 问题

javascript - jQuery 单击事件重新加载页面

jquery - 在 Jquery 中选中/取消选中复选框

javascript - 有没有办法延迟 popstate 事件?

angularjs - 如何在不破坏后退按钮的情况下将触发页面刷新的链接与 Angular 的 html5Mode = true 混合使用?