Делегирование события Jquery не запускается

#jquery

#jquery

Вопрос:

Я собрал следующий JSfiddle:

https://jsfiddle.net/f5ytcova/

 <div class="delFile">Delete</div>   

var are_you_sure = $('<span class="alert alert-danger">Are you sure you wish to remove this file? <span class="yes">Yes</span> | <span class="no">No</span></span>');

$(document).ready(function(){
    $('.delFile').css('cursor','pointer').off('click').on('click',deleteFile);
})

function deleteFile(e){
    df = $(this);
    e.stopPropagation();

    $(df).append(are_you_sure);

    // Gary - I have NO idea why this isn't working??
    $('.delFile').on('click','.no', function() {
    alert('clicked');
        $(this).parent().remove();
    })
}
 

Как вы увидите, я в основном хочу динамически удалить родительский элемент и настроил его на использование делегирования событий в соответствии с ответами в другом месте на переполнение стека. Но по какой-то причине даже при такой настройке родительский элемент не удаляется.

Что я делаю не так?

Комментарии:

1. Почему вы настраиваете обработчик событий (делегированный) в обработчике событий ( deleteFile )? Это почти всегда антипаттерн. Также обратите внимание, что .off('click') в вашем обработчике нет необходимости ready , если у вас действительно нет другого кода, который выполняется до готовности, который добавил бы обработчик щелчков.

2. Кнопка выключения вызвана тем, что ее можно вызывать повторно

3. Нет, это невозможно. 🙂 jQuery вызывает функцию, которую вы передаете ready ровно один раз.

4. Вы используете делегирование событий внутри обработчика событий, что не имеет смысла. Весь смысл использования делегирования событий заключается в том, что вам не нужно условно добавлять обработчик событий; он просто есть, ожидая вызова, если и когда элемент существует. Любые необходимые условия могут управляться с помощью флагов.

Ответ №1:

Что происходит, так это:

  • нажмите delFile
  • добавляет да / нет
  • нажмите Нет
  • запускает код .no и удаляет элемент из DOM (но не из переменной are_you_sure )
  • затем снова запускает delFile click и повторно добавляет элемент jquery, который вы только что удалили

Добавьте return false or, более конкретно, event.stopImmediatePropagation к вашему внутреннему (.no) обработчику щелчков

 $('.delFile').on('click','.no', function() {
    $(this).parent().remove();
    // stop the `.delFile` element getting a click
    return false;
})
 

Обновленная скрипка: https://jsfiddle.net/0nfpox35 /


Обратите внимание, что с вашим исходным кодом вам не нужно делегирование событий, потому что вы добавляете HTML непосредственно перед обработчиком событий. Вы также добавляете объект jquery, что усложняет ситуацию.

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

 function deleteFile(e){
    df = $(this);
    e.stopPropagation();

    $(df).append(are_you_sure);
}

$('.delFile').on('click','.no', function() {
    $(this).parent().remove();
    return false;
})
 

Комментарии:

1. Спасибо — это был буквально ответ копирования / вставки

Ответ №2:

Вы неоднократно добавляете слушателей, добавляете и удаляете .alert элемент, поскольку deleteFile срабатывает не только при delete нажатии, но и при нажатии добавляемого элемента (например .no ).

Я бы прикрепил прослушиватель, чтобы вместо этого удалить родительский are_you_sure элемент, и внутри deleteFile убедитесь, что выбранный элемент не является дочерним .alert элементом, прежде чем добавлять .alert .

Вы также захотите использовать .detach вместо .remove того, чтобы сохранять прослушиватель no событий в несколько delete кликов.

 var are_you_sure = $('<span class="alert alert-danger">Are you sure you wish to remove this file? <span class="yes">Yes</span> | <span class="no">No</span></span>')
  .on('click', '.no', function() {
    $(this).parent().detach();
  });

$(document).ready(function(){
    $('.delFile').css('cursor','pointer').on('click', deleteFile);
})

function deleteFile(e){
    e.stopPropagation();
  if (!e.target.closest('.alert')) {
    // Then the click was on the outer "Delete" text node, not the .alert section
      $(this).append(are_you_sure);
  }
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="delFile">
Delete
</div>