Подтвердить что ты не робот

Более эффективный способ обработки $(window).scroll функций в jquery?

В приведенном ниже коде я проверяю, прокручивается ли окно за определенной точкой, и если это так, измените элемент на использование фиксированной позиции, чтобы он не прокручивался вверху страницы. Единственная проблема заключается в том, что, по-видимому, интенсивная интенсивность клиентской памяти (и действительно болит вниз скорость прокрутки), потому что на каждом отдельном пикселе прокрутки я обновляю атрибуты стиля снова и снова.

Будет ли проверка, если attr уже существует, прежде чем пытаться обновить его, имеет существенное значение? Есть ли совершенно другая и более эффективная практика для получения того же результата?

$(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 использует тот же тип функциональности с их желтыми "Схожие вопросы" и "Справка" меню в правой части этой страницы. Интересно, как они это делают.

4b9b3361

Ответ 1

Один из способов, который вы можете использовать, - установить таймер в событии прокрутки и выполнять основную работу, когда положение прокрутки не изменилось в течение короткого периода времени. Я использую этот метод для событий изменения размера, которые имеют одинаковую проблему. Вы можете поэкспериментировать с тем, какое значение тайм-аута кажется правильным. Более короткое время обновляется с более короткими паузами в прокрутке и, следовательно, может работать чаще во время прокрутки, более длительное время требует, чтобы пользователь фактически приостановил все движения за значимое время. Вам нужно будет поэкспериментировать с тем, какое значение тайм-аута лучше всего подходит для ваших целей, и было бы лучше протестировать на относительно медленном компьютере, так как проблема с задержкой прокрутки была бы наиболее выраженной.

Вот общая идея, как это можно реализовать:

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 каждый раз могут не помочь вам.


Здесь используется метод добавления jQuery, который обрабатывает для вас таймер прокрутки:

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

Ответ 2

Я нашел этот метод намного более эффективным для $(window).scroll()

var userScrolled = false;

$(window).scroll(function() {
  userScrolled = true;
});

setInterval(function() {
  if (userScrolled) {

    //Do stuff


    userScrolled = false;
  }
}, 50);

Отправляйте сообщение Джона Ресига на эту тему.

Еще более эффективным решением было бы установить более длинный интервал, который обнаруживает, если вы рядом с нижней или верхней частью страницы. Таким образом, вам даже не придется использовать $(window).scroll()

Ответ 3

Сделайте вашу функцию немного более эффективной.

Просто проверьте, присутствует ли атрибут стиля/отсутствует, прежде чем удалять/добавлять стили.

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

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

Ответ 4

Задайте здесь некоторую логику. Вам действительно нужно установить atts один раз вверх и один раз вниз. Итак:

var checker = true;
$(window).scroll(function () {

    .......

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