在jQuery中处理$(window).scroll函数的更有效方法? [英] More efficient way to handle $(window).scroll functions in jquery?

查看:258
本文介绍了在jQuery中处理$(window).scroll函数的更有效方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,我正在检查窗口是否正在滚动经过某个点,如果是,则将元素更改为使用固定位置,以使它不会滚动到页面顶部之外.唯一的问题是,这似乎占用了大量客户端内存(并且确实降低了滚动速度),因为在每个单个滚动像素处,我都会在元素上一遍又一遍地更新样式属性.

In the code below, I'm checking to see if the window is being scrolled past a certain point and if it is, change an element to use fixed position so that it doesn't scroll off the top of the page. The only problem is that is seems to be HIGHLY client-side-memory intensive (and really bogs down the scrolling speed) because at every single scroll pixel I am updating the style attributes over and over on the element.

在尝试更新attr之前是否会检查attr是否存在很大差异?是否有一种完全不同且更有效的方法来获得相同的结果?

Would checking if the attr is already there before attempting to update it make a significant difference? Is there a completely different and more efficient practice to get the same result?

$(window).scroll(function () {
    var headerBottom = 165;
    var fcHeight = $("#pnlMainNavContainer").height();

    var ScrollTop = $(window).scrollTop();
    if (ScrollTop > headerBottom) {
        $("#HeaderContentBuffer").attr("style", "margin-top:" + (fcHeight) + "px;");
        $("#AddFieldsContainer").attr("style", "position:fixed;width:320px;top:70px;left:41px;");
    } else {
        $("#HeaderContentBuffer").attr("style", "margin-top: 0px;");
        $("#AddFieldsContainer").removeAttr("style");
    }
});

在键入此内容时,我注意到StackOverflow.com使用相同类型的功能,并在此页面的右侧显示了黄色的类似问题"和帮助"菜单.我想知道他们是怎么做到的.

As I'm typing this, I notice that StackOverflow.com using the same type of functionality with their yellow "Similar Questions" and "Help" menus on the right hand side of this page. I wonder how they do it.

推荐答案

您可以使用的一种方法是在滚动事件上设置计时器,并且仅在滚动位置在短时间内没有变化时才做主要工作.时间.我在具有相同问题的调整大小事件上使用了该技术.您可以尝试使用哪种超时值似乎正确.较短的时间会以较短的滚动暂停进行更新,因此在滚动过程中可能会更频繁地运行,较长的时间要求用户实际将所有运动暂停一段有意义的时间.您将不得不试验哪种超时值最适合您的目的,并且最好在相对较慢的计算机上进行测试,因为这是滚动滞后问题最明显的地方.

One technique you can use is to set a timer on the scroll event and only do the main work when the scroll position hasn't changed for a short period of time. I use that technique on resize events which have the same issue. You can experiment with what timeout value seems to work right. A shorter time updates with shorter pauses in scrolling and thus may run more often during the scroll, a longer time requires the user to actually pause all motion for a meaningful time. You will have to experiment with what timeout value works best for your purposes and it would be best to test on a relatively slow computer since that's where the issue of scroll lag would be most pronounced.

这是如何实现的一般思路:

Here's the general idea how this could be implemented:

var scrollTimer = null;
$(window).scroll(function () {
    if (scrollTimer) {
        clearTimeout(scrollTimer);   // clear any previous pending timer
    }
    scrollTimer = setTimeout(handleScroll, 500);   // set new timer
});

function handleScroll() {
    scrollTimer = null;
    var headerBottom = 165;
    var fcHeight = $("#pnlMainNavContainer").height();

    var ScrollTop = $(window).scrollTop();
    if (ScrollTop > headerBottom) {
        $("#HeaderContentBuffer").attr("style", "margin-top:" + (fcHeight) + "px;");
        $("#AddFieldsContainer").attr("style", "position:fixed;width:320px;top:70px;left:41px;");
    } else {
        $("#HeaderContentBuffer").attr("style", "margin-top: 0px;");
        $("#AddFieldsContainer").removeAttr("style");
    }
}

您还可以通过在滚动开始时缓存一些选择器来加快滚动功能,从而不必每次都重新计算它们.在这个地方,每次创建jQuery对象的额外开销可能对您没有帮助.

You may also be able to speed up your scroll function by caching some of the selectors when the scrolling first starts so they don't have to be recalculated each time. This is one place where the extra overhead of creating a jQuery object each time might not be helping you.

这是一个jQuery附加方法,可为您处理滚动计时器:

Here's a jQuery add-on method that handles the scrolling timer for you:

(function($) {
    var uniqueCntr = 0;
    $.fn.scrolled = function (waitTime, fn) {
        if (typeof waitTime === "function") {
            fn = waitTime;
            waitTime = 500;
        }
        var tag = "scrollTimer" + uniqueCntr++;
        this.scroll(function () {
            var self = $(this);
            var timer = self.data(tag);
            if (timer) {
                clearTimeout(timer);
            }
            timer = setTimeout(function () {
                self.removeData(tag);
                fn.call(self[0]);
            }, waitTime);
            self.data(tag, timer);
        });
    }
})(jQuery);

正在运行的演示: http://jsfiddle.net/jfriend00/KHeZY/

您的代码将这样实现:

$(window).scrolled(function() {
    var headerBottom = 165;
    var fcHeight = $("#pnlMainNavContainer").height();

    var ScrollTop = $(window).scrollTop();
    if (ScrollTop > headerBottom) {
        $("#HeaderContentBuffer").attr("style", "margin-top:" + (fcHeight) + "px;");
        $("#AddFieldsContainer").attr("style", "position:fixed;width:320px;top:70px;left:41px;");
    } else {
        $("#HeaderContentBuffer").attr("style", "margin-top: 0px;");
        $("#AddFieldsContainer").removeAttr("style");
    }
});

这篇关于在jQuery中处理$(window).scroll函数的更有效方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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