исчезать / выводить баннер - PullRequest
5 голосов
/ 19 декабря 2011

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

мой код ....

$(Document).ready(function () {
var images = new Array();
images[0] = "#bannerImageOne";
images[1] = "#bannerImageTwo";
$('#homeCarousel img').hide();

for (var i in images) {
    setTimeout(fadeInOut(i, images), 5000);
    //alert(i);
}
});


function fadeInOut(i, images) {
$(images[i]).fadeIn("slow").delay(2000).fadeOut();
//alert(images[i]);
}

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

спасибо ....

1 Ответ

9 голосов
/ 19 декабря 2011

Обзор

Этот ответ состоит из двух частей: справка по фактическому опубликованному вами коду и рекомендация для другого способа сделать это

справка по опубликованному вами коду

Этот код:

for (var i in images) {
    setTimeout(fadeInOut(i, images), 5000);
    //alert(i);
}

... имеет одну главную и одну второстепенную проблему:

  1. Основная проблема: Вы звоните функция fadeInOut и передача возвращаемого значения в setTimeout, как и в любой другой раз, когда вы делаете function1(function2(arg, arg2));.Вместо этого измените строку setTimeout на:

    setTimeout(createFader(i, images), 5000);
    

    ... и добавьте функцию createFader, которая выглядит следующим образом:

    function createFader(index, array) {
        return function() {
            fadeInOut(index, array);
        };
    }
    

    Функция createFader создаетфункция, которая при вызове вызовет fadeInOut с аргументами, которые вы ей передали.Вы не можете просто сделать это:

    setTimeout(function() {  // <== WRONG, WILL NOT WORK
        fadeInOut(i, images);
    }, 5000);
    

    ... потому что анонимная функция (то есть замыкание ) получит постоянную ссылку *От 1039 * до i и images, и поэтому, когда истечет время ожидания, он будет использовать любые их значения , а затем , а не то, что они были при создании функции.Подробнее: Затворы не сложны

    (Не используйте строки с setTimeout в качестве другого ответа предлагает предложил.)

  2. for..in предназначен для циклического перебора перечисляемых имен свойств объекта, не для циклического перебора индексов массива.В тривиальной среде это в основном работает, но это плохая привычка, что укусит вас , если вы не совсем понимаете, что делаете.Подробнее здесь: Мифы и реальность for..in Если вы используете jQuery, и если это нормально, накладывать издержки на пару вызовов функций, $.each отлично подходит для циклического перебора массивов (за исключением того, что он не идеален для разреженных массивов, но ваш не редкий).

Отдельно обратите внимание, что new Array() лучше писать [] и на самом деле вы можете поместить записи непосредственно в квадратные скобки, а не выполнять задание по факту.И, конечно, это document (во всех строчных буквах), а не Document с заглавной буквы D.

Итак, все это вместе:

$(document).ready(function () {
    var images = [
        "#bannerImageOne",
        "#bannerImageTwo"
    ];
    var i;

    $('#homeCarousel img').hide();

    for (i = 0; i < images.length; ++i) {
        setTimeout(createFader(i, images), 5000);
    }
});

function createFader(index, array) {
    return function() {
        fadeInOut(index, array);
    };
}

function fadeInOut(i, images) {
    $(images[i]).fadeIn("slow").delay(2000).fadeOut();
    //alert(images[i]);
}

Также обратите внимание, что я переехалобъявление i в верхней части функции, потому что именно там движок JavaScript все равно его видит (подробности: Плохо, неправильно var).

Если у вас нет действительно веской причины, по которой fadeInOut должна быть глобальной функцией, я бы переместил ее (и createFader) в функцию, которую вы передаете ready, поэтому мы вообще не создаем глобальные символы.Это также позволяет им обоим использовать images напрямую, поэтому нам не нужно передавать ссылку на массив (не то, что это дорого, это совершенно нормально).Это будет выглядеть так:

$(document).ready(function () {
    var images = [
        "#bannerImageOne",
        "#bannerImageTwo"
    ];
    var i;

    $('#homeCarousel img').hide();

    for (i = 0; i < images.length; ++i) {
        setTimeout(createFader(i, images), 5000);
    }

    function createFader(index) {
        return function() {
            fadeInOut(index);
        };
    }

    function fadeInOut(i) {
        $(images[i]).fadeIn("slow").delay(2000).fadeOut();
        //alert(images[i]);
    }
});

Это работает, потому что, помещая функции внутри анонимной функции, которую вы передаете в ready, мы делаем их замыканиями в контексте контекставызов этой анонимной функции.(См. Ссылку выше о замыканиях.) Даже после того, как функция возвращается (что она делает почти сразу), контекст сохраняется в памяти и предоставляет удобный контейнер для наших личных данных.

Рекомендация для другого способа

Поскольку все, что делает вызов setTimeout, - это задержка запуска fadeIn на 5 секунд, код может быть намного проще, если вы используете delay (поскольку вы уже должны поставить паузу междуfadeIn и fadeOut):

$(document).ready(function () {
    var images = [
        "#bannerImageOne",
        "#bannerImageTwo"
    ];

    $('#homeCarousel img').hide();

    $.each(images, function(index, id) {
        $(id).delay(5000).fadeIn("slow").delay(2000).fadeOut();
    });
});

Или сохранение fadeInOut в качестве отдельной функции:

$(document).ready(function () {
    var images = [
        "#bannerImageOne",
        "#bannerImageTwo"
    ];

    $('#homeCarousel img').hide();

    $.each(images, function(index, id) {
        fadeInOut(id, 5000);
    });

    function fadeInOut(id, delay) {
        $(id).delay(delay).fadeIn("slow").delay(2000).fadeOut();
    }
});

delay занимает место setTimeout ивсе изображения начинают исчезать через 5 секунд.(Я также привел пример использования $.each для пролистывания массива.) Если вы хотите, чтобы они постепенно исчезали в последовательно , вы могли бы умножить задержку на index:

$.each(images, function(index, id) {
    $(id).delay(5000 * (index + 1)).fadeIn("slow").delay(2000).fadeOut();
});

или

$.each(images, function(index, id) {
    fadeInOut(id, 5000 * (index + 1));
});

... что приведет к задержке первого изображения на 5 секунд, второго на 10 и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...