JQuery滚动没有触发滚动

我使用以下javascript来制作“粘性”导航,这使得当用户滚动浏览器时导航被固定到屏幕顶部。 此代码工作正常,但是当元素变为粘滞并且元素的位置设置为“固定”时,主体中所有后续元素的位置“跳起”以占据通过更改元素而创建的间隙相对于固定,并产生轻微的’颠簸’效果。 为了解决这个问题,我尝试在将元素更改为固定时向滚动y位置添加偏移,但这会通过再次触发滚动function导致循环,并且页面滚动到页面的底部。

所以我的问题是 – 如何在下面的函数中添加一个偏移到滚动位置? 即,如何在$(window).scroll函数中设置滚动位置, 而不将$(window).scroll函数触发到循环中?

$(window).scroll(function (event) { var y = $(this).scrollTop(); var top = $('#main-navigation').offset().top; if (y >= top) { $('#navigation').addClass('fixed'); } else { $('#navigation').removeClass('fixed'); } }); 

很感谢任何forms的帮助

一般解决方案

以下是防止循环的一般解决方案:

 var lastScrollTop = 0; var defaultScrollHandler = function(e) { var y = $(this).scrollTop(); //change event handlers $(window).off("scroll", defaultScrollHandler); $(window).on("scroll", tmpScrollHandler); var jumpHeight = 200; if(lastScrollTop > y) jumpHeight *= -1; var newY = y + jumpHeight; $(window).scrollTop(y + jumpHeight); }; var tmpScrollHandler = function() { lastScrollTop = $(this).scrollTop(); //change event handlers back $(window).off("scroll", tmpScrollHandler); $(window).on("scroll", defaultScrollHandler); }; $(window).on("scroll", defaultScrollHandler); 

http://jsfiddle.net/udcwgyub/

在设置新的滚动位置之前,您可以禁用当前事件处理程序并为scroll事件注册另一个处理程序。 设置新的滚动位置后,将调用另一个处理程序。 此处理程序将禁用自身并再次注册实际处理程序。

更好的解决方案

我认为在你的情况下你可以更好地用虚拟元素替换静态导航,虚拟元素应该与导航具有相同的高度。

 var navOffset = $("nav").offset().top; $("#dummyNav").height($("nav").innerHeight()); $(window).scroll(function(){ var y = $(this).scrollTop(); var $nav = $("nav"); var $dummyNav = $("#dummyNav"); if(y >= navOffset) { if(!$nav.hasClass("fixed")) { $nav.addClass("fixed"); $dummyNav.show(); } } else if($nav.hasClass("fixed")) { $nav.removeClass("fixed"); $dummyNav.hide(); } }); 

http://jsfiddle.net/wdup394c/

最简单的解决方案是临时替换滚动事件订阅。

 // initial subscribe to scroll event this.$el.on("scroll", this.handleScroll); // unsubscribe initial handler and subscribe fake handler before manual scroll this.$el.off("scroll"); this.$el.on("scroll", () => { this.$el.off("scroll"); this.$el.on("scroll", this.handleScroll); }); // scroll manually this.$el.scrollTop(0); 

但是,如果在手动滚动期间没有发生滚动事件(在this.$el.scrollTop(0);期间this.$el.scrollTop(0); ),则不会在第一个滚动事件上调用处理程序。 在这种情况下,在第一个事件期间,假事件将被取消订阅,而原始事件将被重新订阅,但不会被调用。