jQuery: последний дочерний элемент не обновляется при добавлении дополнительных дочерних элементов?

0

У меня есть набор входов, где я хотел бы добавить еще один вход, когда последний вход, отображаемый в настоящее время, получает фокус. Форма начинается с 2 входов.

$('.answer_fields input:last-child').focus(function(event) {
        var nextfield = $('.answer_fields input').length + 1;
        $('.answer_fields').append('<input class="form-control answer_field" placeholder="Answer option #' + nextfield +'" id="answer' + nextfield +'">');
    });

В настоящее время дополнительные поля добавляются только тогда, когда второй вход (исходный "последний-ребенок") получает фокус.

Проверка источника, похоже, показывает, что входы добавляются в DOM, как и ожидалось. Что мне не хватает?

  • 2
    Вам нужно использовать делегирование событий.
  • 3
    Потому что ваша функция .focus добавляется только к тем элементам, которые существуют на момент запуска селектора.
Показать ещё 1 комментарий
Теги:

2 ответа

3
Лучший ответ

Селектор jQuery оценивается ONCE во время запуска кода для установки обработчика события .focus(). Он не корректируется в реальном времени, поскольку все меняется. Вы можете переключиться на делегирование событий, если вы хотите этого типа поведения.

Аналогичный обработчик событий, который будет оцениваться в реальном времени, будет выглядеть так:

$(some common parent selector).on("focus", ".answer_fields input:last-child", function() {
    // code here
});

Рабочая демонстрация: http://jsfiddle.net/jfriend00/ZZLPJ/


Во-первых, ваш исходный код не работал, потому что вы добавляли обработчики событий к определенным элементам, которые существовали в момент запуска вашего первого кода. Какие события, к которым вы подключили обработчики событий, не изменились по мере изменения вашей структуры в будущем, поэтому новые элементы не будут иметь обработчиков событий, а часть :last-child селектора вашего селектора не будет переоценена.

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

Чтобы дать вам представление, это то, что я называю "статическими" обработчиками событий:

$(".test:last-child").focus(fn);
$(".test:last-child").on("focus", fn);

Это делегированные (и, следовательно, динамические) обработчики событий:

$("#parent").on("focus", ".test:last-child", fn);

Дополнительные сведения по этой теме см. В следующих ответах:

jQuery.live() vs.on() метод добавления события click после загрузки динамического html

Работает ли jQuery.on() для элементов, которые добавляются после создания обработчика событий?

Должны ли все события jquery быть привязаны к $ (документу)?

Просто проверено, чтобы быть уверенным, и событие фокуса делает событие пузыря событий, которое будет работать с ним.

1

Это обычный вопрос для людей, начинающих использовать jQuery. Оказывается, что названные eventListeners (то есть $.fn.click, $.fn.focus и т.д.) $.fn.focus прослушиватель событий к каждому соответствующему элементу DOM при первой загрузке страницы. Эти слушатели определяются на самих согласующего элемента, а это означает, что каждый из них является уникальным для элемента он присоединен.

Вы услышите этот метод по сравнению с тем, что обычно называют делегацией событий. Делегирование событий включает привязку ровного слушателя к общему родительскому элементу, который будет проверять атрибут event.target чтобы убедиться, что он соответствует вашему критерию (в вашем случае, .answer_fields input:last-child). Это отличается от прикрепления уникального слушателя к каждому элементу DOM, который вы хотите настроить, поскольку он позволяет динамически добавлять новые узлы в DOM, которые затем будут обрабатываться слушателем родительского узла, как и любой другой узел.

Чтобы выполнить делегирование делегирования с помощью jQuery, используйте .on() для общего предка (я буду использовать document в качестве примера) и выслушайте все соответствующие элементы в качестве второго аргумента вызова функции:

$(document).on('focus', '.answer_fields input:last-child', function(event) {
    // your code here
});

Это не только решит вашу проблему с динамически создаваемыми элементами DOM, но делегирование событий значительно улучшит производительность вашей страницы, уменьшив общее количество прослушивателей событий, связанных с элементами в DOM.

Для получения дополнительной информации о делегировании событий я бы посоветовал вам проверить этот учебник и этот вопрос SO

  • 0
    Отличный ответ - очень тщательно! Спасибо за объяснение.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню