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

JQuery.when(). done() не работает

Я хотел бы начать с того, что я новичок в jQuery, и я подозреваю, что я просто делаю что-то глупое, так что, надеюсь, это будет очень просто для кого-то.

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

function ResetMenu(){
    jQuery(".mobile-menu").find(".sub-menu").slideUp(100);
    jQuery(".mobile-menu").find(".menu-item-has-child").removeClass("open");
};

function OpenSubmenu(){
    jQuery(this).next("ul").slideDown(100);
    jQuery(this).parent().addClass("open");
};

jQuery("li.menu-item-has-children > a").click(function(){

    if(jQuery(this).parent().hasClass("open")){
        jQuery(".mobile-menu").find(".sub-menu").slideUp(100);
        jQuery(this).parent().removeClass("open");
    } else {
        jQuery.when(ResetMenu()).done(OpenSubmenu());
    }
    return false;
});

Любая помощь будет принята с благодарностью. Спасибо!

Ronel

4b9b3361

Ответ 1

Это распространенная ошибка в использовании jQuery.when().

jQuery.when() требует promises в качестве аргументов. У него нет магических способностей знать, когда функции, которые вы передаете, как-то сделаны. Эти функции ДОЛЖНЫ возвращать promises, которые разрешаются или отклоняются при выполнении базового кода, и затем вы можете передать эти promises в jQuery.when().

Ваша функция ResetMenu() ничего не возвращает, поэтому ваш jQuery.when() не ждет ничего. Он немедленно выполняет обработчик .then() (что выглядит не так, как вы хотите).

Итак, в этой строке:

jQuery.when(ResetMenu()).done(OpenSubmenu());

ResetMenu() ДОЛЖЕН вернуть обещание jQuery.when() знать, когда это будет сделано.

Вы можете исправить ResetMenu() для работы таким образом:

function ResetMenu(){
    return jQuery(".mobile-menu").find(".sub-menu").slideUp(100).promise().then(function() {
        // remove this class when the animation has completed
        jQuery(".mobile-menu").find(".menu-item-has-child").removeClass("open");
    });
};

И, кроме того, вам нужно изменить способ передачи функции на .done() на это, что делает это просто ссылкой на функцию, которая может быть выполнена LATER и привязывает к ней соответствующее значение this:

jQuery.when(ResetMenu()).done(OpenSubmenu.bind(this));

Примечание. .bind(this) предполагает, что this является подходящим значением. Вы можете передать любое значение, соответствующее этому значению, и оно станет значением this внутри OpenSubmenu() при его выполнении.

Ответ 2

Когда вы передаете объект без обещаний $.when(), вызывающие вызовы, переданные в done(), вызываются немедленно, в вашем случае, когда ResetMenu не возвращает ничего, вызываемое OpenSubmenu, есть и другая проблема - вам не следует ссылаться непосредственно на OpenSubmenu (добавив ()), вам нужно передать ссылку на функцию done()

function ResetMenu() {
    jQuery(".mobile-menu").find(".menu-item-has-child").removeClass("open");
    return jQuery(".mobile-menu").find(".sub-menu").slideUp(100).promise();

};

function OpenSubmenu() {
    jQuery(this).next("ul").slideDown(100);
    jQuery(this).parent().addClass("open");
};

jQuery("li.menu-item-has-children > a").click(function () {

    if (jQuery(this).parent().hasClass("open")) {
        jQuery(".mobile-menu").find(".sub-menu").slideUp(100);
        jQuery(this).parent().removeClass("open");
    } else {
        jQuery.when(ResetMenu()).done(OpenSubmenu);
    }
    return false;
});