更改滚动时的URL哈希并保持后退按钮正常工作 [英] Change URL hash on scroll and keep back button working

查看:67
本文介绍了更改滚动时的URL哈希并保持后退按钮正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在具有固定顶部菜单和锚导航的一页布局中,我有一个"scrollspy",可更改滚动上的片段标识符,根据滚动位置为菜单链接提供活动类,并使用Velocity.js.

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

这是jsfiddle.

 //jQuery可以在DOM上使用//使用VelocityJS进行页内滚动动画//------------------------------------------------////https://john-dugan.com/fixed-headers-with-hash-links/$('.menu-a').on('click',function(e){var hash = this.hash,$哈希= $(哈希)addHash = function(){window.location.hash =哈希;};$ hash.velocity("scroll",{持续时间:700,缓动:[.4,.21,.35,1],完成:addHash});e.preventDefault();});//菜单项和片段标识符的ScrollSpy//------------------------------------------------////https://jsfiddle.net/mekwall/up4nu/$ menuLink = $('.menu-a')var lastId,//对应于菜单项的锚点scrollItems = $ menuLink.map(function(){var item = $($(this).attr("href"));if(item.length){返回项目;}});$(window).scroll(function(){//获取容器滚动位置var fromTop = $(this).scrollTop()+ 30;//或#navigation height的值//获取当前滚动项的IDvar cur = scrollItems.map(function(){如果($(this).offset().top< fromTop)返回这个;});//获取当前元素的IDcur = cur [cur.length-1];var id = cur&&当前长度?cur [0] .id:";如果(lastId!== id){lastId = id;//设置/删除活动类$菜单链接.parent().removeClass("active").end().filter("[href ='#" + id +']").parent().addClass("active");}//如果浏览器支持,我们还可以更新URL//http://codepen.io/grayghostvisuals/pen/EtdwL如果(window.history&&window.history.pushState){history.pushState(",document.title,'#'+ id);}}); 

使用上面的代码,可以很好地进行以下操作:

  • 使用VelocityJS进行滚动动画单击菜单链接时,哈希或片段标识符可以很好地更新.

  • 活动类在滚动时被赋予相应的菜单链接.

  • 在滚动而不是单击菜单链接时,片段标识符也可以很好地更新.

问题
第1部分:当您在小提琴上滚动一小段然后单击后退"按钮时,您会看到滚动条以完全相同的方式移动",并记住已完成的滚动.

我需要后退按钮才能正常工作.a)返回浏览器历史记录并返回到您所在的页面/站点,然后b)单击锚定链接(i),然后单击锚定链接(ii),然后单击返回按钮时,页面应返回到锚定链接(i).

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

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

修改我想我可能在在这里找到了一种解决方案,将对其进行测试,然后在我能解决此问题时进行详细答复.>

相关:
平滑滚动并获取Firefox上带有popState的后退按钮-需要单击两次
jQuery在页面后退按钮中滚动
在不滚动页面的情况下修改document.location.hash

如何检测浏览器后退按钮事件-跨浏览器

解决方案

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

还有一篇很好的文章,其中包括 pushState replaceState

Unfortunately what it also does, when clicking the browser back button it takes me through all the steps of the scrolled way, meaning I load the site and scroll down and up a tiny bit and then hit the back button frequently the browser will also scroll down and up but won't go to either the last visited id or back in browser history actually.

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);
    }   
});

With the above code the following works fine:

  • The hash or fragment identifier updates fine when clicked on the menu link using VelocityJS for the scrolling animation.

  • The active class is given to the corresponding menu link on scrolling.

  • The fragment identifier also updates fine when scrolling instead of clicking the menu link.

Question
Part 1: When you scroll a tiny bit on the fiddle and then hit the back button you will see that the scrollbar "travels" the exact same way, remembering the scrolling that was done.

I need the back button to work like it normally does. a) Either go back in browser history and return to the page/site you were on and b) when having clicked an anchor link (i) and then anchor link (ii) and then the back button the page should go back to anchor link (i).

Part 2: Since history.pushState is not supported in IE8 I am looking for a way to use window.location.hash = $(this).attr('id'); instead. No matter what I have tried towards the end of the code I simply cannot get window.location.hash = $(this).attr('id'); to work. I don't really want to use HistoryJS or something for this but am interested to learn this and write it myself.

Apart from the back button broken behaviour all the other behaviour that I want is already there, now I just need to fix the back button behaviour.

edit I think I might have found a solution here, will test and then reply in detail if I get this to work.

Related:
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

解决方案

To answer the first part of your question, if you don't want to pollute the browser's history, you can use history.replaceState() instead of history.pushState(). While pushState changes the URL and adds a new entry to the browser's history, replaceState changes the URL while modifying the current history entry instead of adding a new one.

There is also a good article including differences between pushState and replaceState on MDN.

这篇关于更改滚动时的URL哈希并保持后退按钮正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆