5

我正在处理一个带有固定菜单的页面,该菜单在用户从顶部滚动一定距离后拾取,并且当他们向下滚动页面时,菜单中的不同链接被赋予一个改变颜色的类。所有这一切似乎在 Chrome 和 Safari 中运行良好,但在 Firefox 中,页面冻结在顶部。我想知道它是否不断地循环一些代码......基本上冻结了窗口。

这是我的代码。

$.localScroll({
    onBefore: function() {
        $('body').data('scroll-executing', true);

    },
    onAfter: function() {
        $('body').data('scroll-executing', false);
        $(window).trigger("scroll");
    }
});

$(window).scroll(function () {
    if ($(this).scrollTop() > 259) {
        $('.nav').addClass("f-nav");
    } else {
        $('.nav').removeClass("f-nav");
    }
});

$(window).scroll(function() { 
    if ($('body').data('scroll-executing')) {
        return;
    }
    // find the a with class 'active' and remove it
    $("a").removeClass('active');
    // get the amount the window has scrolled
    var scroll = $(window).scrollTop();
    // add the 'active' class to the correct #nav based on the scroll amount

    if (scroll > 2150) {
        $("#nav_3").removeClass('active');
        $("#nav_5").attr('class', 'active');
        setHash("contact");

    } else if (scroll > 1300) {
        $("#nav_2").removeClass('active');
        $("#nav_3").attr('class', 'active');
        setHash("portfolio");

    } else if (scroll > 400) {
        $("#nav_2").attr('class', 'active');
        setHash("about");

    } else if (scroll <= 380) { //when I remove this section, the problem goes away.
        $("#nav_1").attr('class', 'active');
        setHash("home");
    }

});

我忘了添加 setHash 定义。这里是。

setHash = function(hash) {
    var scrollmem = $('body').scrollTop();
    window.location.hash = hash;
    $('html,body').scrollTop(scrollmem);
}

我还注意到 CPU 上升到 100%,我似乎不知道为什么。

问题出在以 else if (scroll <= 380) 开头的代码的第三部分。我通过消除过程弄清楚了这一点。任何人都可以看到它循环或做一些永远不会结束的事情......或者解释为什么 Firefox 在页面顶部冻结?

我对所有这些都是新手......我在过去几天刚刚拿起 jquery,我基本上一直在谷歌搜索并调整代码以使其适合我的需要。

任何帮助将不胜感激。

4

3 回答 3

3

在滚动事件上执行太多代码是多余的,在每次滚动时,浏览器都会触发滚动事件数百次,您可以考虑使用具有类似throttleor方法的库debounce

http://documentcloud.github.com/underscore/#throttle

将处理程序附加到窗口滚动事件是一个非常非常糟糕的主意。根据浏览器的不同,滚动事件可能会触发很多,并且将代码放入滚动回调中会减慢滚动页面的任何尝试(不是一个好主意)。因此,滚动处理程序中的任何性能下降只会使整体滚动性能更加复杂。相反,最好使用某种形式的计时器每 X 毫秒检查一次,或者附加一个滚动事件,并且只在延迟后(或者甚至在给定数量的执行之后 - 然后延迟)运行您的代码。 http://ejohn.org/blog/learning-from-twitter/

于 2012-09-14T17:07:31.237 回答
1

基本上你在滚动事件中执行了太多。正如@undefined 所说,浏览器调用它的次数比你想象的要多得多。一些技巧:

当在一个将被多次调用的函数中时,已经创建了你的 jQuery 对象。这样,每次调用该函数时,它都不会重新创建相同的 jQuery 对象。

var nav2 = $("#nav_2");
$(window).scroll(function() {
   ...
   nav2.removeClass('active');
   ...
});

同样,当一遍又一遍地调用时,添加和删除类会消耗大量的处理周期——尤其是当您访问整个类的元素时,例如在$('.nav').addClass("f-nav");.

相反,仅当类不存在时才尝试添加/删除它们。就像是:

var alreadyAdded = false;
var alreadyRemoved = false;
$(window).scroll(function () {
    if ($(this).scrollTop() > 259) {
      if(!alreadyAdded){
        $('.nav').addClass("f-nav");
        alreadyAdded = true;
        alreadyRemoved = false;
      }
    } else if(!alreadyRemoved) {
        $('.nav').removeClass("f-nav");
        alreadyAdded = false;
        alreadyRemoved = true;
    }
});

尽管如此,它仍然可能会缓慢滚动,所有这些代码都附加到滚动事件。也许还有另一种方法可以获得相同的效果。如果 Firefox 冻结,我只能想象这在 IE 中一定有多慢。

于 2012-09-14T17:24:34.330 回答
0

除了其他问题,$('body').scrollTop()在 Firefox 中总是会返回 0。setHash()运行时$('html,body').scrollTop(scrollmem);},它会跳转到屏幕顶部,看起来就像用户第一次加载页面时卡在屏幕顶部一样。$(window).scrollTop(),结合节流,将解决这个问题。

于 2012-09-14T21:19:49.460 回答