javascript - 更改滚动时的 URL 哈希值并保持后退按钮正常工作

标签 javascript jquery html url back

在具有固定顶部菜单和 anchor 导航的单页布局上,我有一个“scrollspy”,它可以更改滚动上的片段标识符,根据滚动位置为菜单链接提供一个事件类,并使用动画滚动到 anchor Velocity.js.

不幸的是,它也做了什么,当点击浏览器后退按钮时,它会带我完成滚动方式的所有步骤,这意味着我加载网站并向下和向上滚动一点点,然后经常点击后退按钮,浏览器将也可以向下和向上滚动,但实际上不会转到上次访问的 ID 或返回浏览器历史记录。

Here is the jsfiddle.

// jQuery on DOM ready

// In-Page Scroll Animation with VelocityJS
// ------------------------------------------------ //
// https://john-dugan.com/fixed-headers-with-hash-links/
$('.menu-a').on('click', function(e) {
    var hash  = this.hash,
        $hash = $(hash)

        addHash = function() {
            window.location.hash = hash;
        };      

      $hash.velocity("scroll", { duration: 700, easing: [ .4, .21, .35, 1 ], complete: addHash });

    e.preventDefault();
});

// ScrollSpy for Menu items and Fragment Identifier
// ------------------------------------------------ //
// https://jsfiddle.net/mekwall/up4nu/
$menuLink           = $('.menu-a')

var lastId,
    // Anchors corresponding to menu items
    scrollItems = $menuLink.map(function(){
    var item = $($(this).attr("href"));
        if (item.length) { return item; }
    });


$(window).scroll(function(){
    // Get container scroll position
    var fromTop = $(this).scrollTop()+ 30; // or the value for the #navigation height

    // Get id of current scroll item
    var cur = scrollItems.map(function(){
        if ($(this).offset().top < fromTop)
        return this;
    });

    // Get the id of the current element
    cur = cur[cur.length-1];
    var id = cur && cur.length ? cur[0].id : "";
    if (lastId !== id) {
        lastId = id;

        // Set/remove active class
        $menuLink
        .parent().removeClass("active")
        .end().filter("[href='#"+id+"']").parent().addClass("active");
    }

    // If supported by the browser we can also update the URL
    // http://codepen.io/grayghostvisuals/pen/EtdwL
    if (window.history && window.history.pushState) {
        history.pushState("", document.title,'#'+id);
    }   
});

使用上面的代码,以下工作正常:

  • 当使用 VelocityJS 滚动动画点击菜单链接时,哈希或片段标识符更新正常。

  • 在滚动时将事件类赋予相应的菜单链接。

  • 片段标识符在滚动而不是单击菜单链接时也能正常更新。

问题
第 1 部分:当您在 fiddle 上滚动一点点然后点击后退按钮时,您会看到滚动条以完全相同的方式“移动”,记住已完成的滚动。

我需要后退按钮像往常一样工作。 a) 返回浏览器历史记录并返回到您所在的页面/站点,然后 b) 单击 anchor 链接 (i),然后单击 anchor 链接 (ii),然后单击后退按钮,页面应返回到 anchor 链接 (i)。

第 2 部分: 由于 IE8 不支持 history.pushState 我正在寻找一种使用 window.location.hash = $(this) 的方法.attr('id'); 代替。无论我在代码末尾尝试了什么,我都无法让 window.location.hash = $(this).attr('id'); 工作。我真的不想为此使用 HistoryJS 或其他东西,但有兴趣学习并自己编写它。

除了后退按钮损坏的行为外,我想要的所有其他行为都已经存在,现在我只需要修复后退按钮的行为。

编辑 我想我可能找到了解决方案 here , 将测试然后详细回复如果我让它工作。

相关:
smooth scrolling and get back button with popState on Firefox - need to click twice
jQuery in page back button scrolling
Modifying document.location.hash without page scrolling

How to Detect Browser Back Button event - Cross Browser

最佳答案

要回答你问题的第一部分,如果你不想污染浏览器的历史记录,你可以使用 history.replaceState() 而不是 history.pushState()pushState 更改 URL 并将新条目添加到浏览器的历史记录中,replaceState 更改 URL 的同时修改当前历史记录条目而不是添加新条目。

还有一篇很好的文章介绍了 pushStatereplaceState 之间的区别 on MDN .

关于javascript - 更改滚动时的 URL 哈希值并保持后退按钮正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37419183/

相关文章:

javascript - 在 jquery 选择器中访问 div

javascript - 我的 JS 实时应用程序中的垃圾收集时间太长

javascript - 无法突出显示可切换的 div 内的代码

javascript - 如何在javascript中从表中获取列名称和第一行值?

javascript - 使用 javascript 形成两个 Action

jquery - 使用 jQuery 切换 div 和隐藏的 div

javascript - 如果字符串类似于 'price 0 &euro;',则替换innerHTML

jquery - 在 Jquery 中,如何将 If/else 与 window.location.pathname.indexOf 一起使用?

HTML 表单输入标题样式

javascript - 将 React 添加到现有页面并在 .js 中获取 URL 参数