Каков правильный способ добавления слушателей к новым элементам после использования AJAX для получения html-контента? (JQuery, JavaScript)

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

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

Спасибо!


person Lumin    schedule 23.07.2013    source источник
comment
Используйте делегирование событий.   -  person SLaks    schedule 24.07.2013
comment
То, что вы описали как свою мысль, - это, по сути, то, как это обрабатывается в JQM, если вы используете глобальный скрипт, вы просто слушаете pageinit с определенным идентификатором. Да, он может стать большим. Для событий, которые являются общими для всех страниц, вы можете сэкономить кодирование, используя делегирование событий.   -  person Kevin B    schedule 24.07.2013


Ответы (5)


Два пути:

1) Привязать к нединамическому родительскому контейнеру, используя .on()

$('.some-parent-class').on('click', '.element', function() {
  // DO STUFF!
});

2) Привязать новые элементы после завершения вызова ajax

$.ajax(url, {
  // ajax options
}).done( function(data) {
  var newEl = $('<div class="element"></div>');
  // Setup your newEl with data here...
  newEl.on('click', function() {
    // do stuff
  });
  newEl.appendTo($('.some-parent-class'));
});

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

person Populus    schedule 23.07.2013
comment
Ваш второй пример странный. Что происходит, когда существуют существующие элементы .element (например, из предыдущих запросов AJAX)? Вы связываете два события. Этот селектор должен быть более конкретным (или применяться только к ответу на запрос AJAX). - person Ian; 24.07.2013
comment
это общий случай.. вы можете указать более конкретный селектор, если хотите - person Populus; 24.07.2013
comment
Да, я думаю, это здорово :) - person Ian; 24.07.2013
comment
Разве это не должно быть просто .done(function(data){ $('.element', data).click(function(){ }); });? - person Ohgodwhy; 24.07.2013
comment
@Ohgodwhy зависит от того, что вы хотите с ним делать: x, и какие данные возвращаются из вызова ajax. - person Populus; 24.07.2013
comment
Но ОП сказал: I am not sure what's the most efficient way to bind listeners to those elements from the new content page. И поскольку вы отвечаете на вопрос ОП, вы должны правильно ответить на это в моей книге. - person Ohgodwhy; 24.07.2013
comment
@Ohgodwhy Очень возможно. Очевидно, есть несколько вариантов того, что вы можете сделать с data и на что ориентироваться для привязки событий. - person Ian; 24.07.2013
comment
@Ohgodwhy Вы цитируете OP об эффективности ... так почему вы привязываете события к $(document)? Нет никакой разницы с кодом этого ответа и тем, что вы предлагаете. Это не более/менее эффективно - person Ian; 24.07.2013
comment
@ Ян Неправильно. Я не цитирую эффективность, я цитирую работу с возвращаемыми данными из ajax-вызова. var newEl = $('<div class="element"></div>'); не работает ни с какими возвращаемыми данными, тогда как $('.element', data) выбирает из возвращаемого набора данных. Более того, не имея возможности увидеть, что такое HTML-разметка, я не могу узнать, какой более близкий статический родительский элемент существует. Я просто пытаюсь убедиться, что на вопрос дан правильный ответ, потому что, если бы я использовал это, я бы предположил, что мне нужно создать новый элемент в функции done, а не использовать возвращенные элементы - person Ohgodwhy; 24.07.2013
comment
@Ohgodwhy Ваш комментарий сказал: «Но ОП сказал: I am not sure what's the most efficient way. В любом случае, $('.element', data) не работает, когда data является JSON. Populus только что предоставил базовую настройку того, как с этим справиться. Возможно, им нужно перебрать все в data и добавить элемент к чему-то вроде newEl Populus, который они установили. Вы правы, хотя, вероятно, это можно было бы объяснить лучше, поэтому некоторые вещи не предполагаются - person Ian; 24.07.2013
comment
если вы беспокоитесь об эффективности, привязка к $(document) далека от эффективности, так как событие должно пройти весь путь вверх по всему дереву элементов dom, прежде чем оно будет выполнено. - person Populus; 24.07.2013
comment
привязка к $(document) также может быть неправильной, так как у вас может быть промежуточный элемент, который делал e.stopPropagation() - person Populus; 24.07.2013
comment
Большое спасибо, ребята! :) - person Lumin; 24.07.2013

Используйте функцию jQuery .on() для обработки делегирования событий. Первый элемент, который вы предоставляете, является статическим элементом (никогда не удаляется/не заменяется). первый аргумент — это событие, которому вы хотите делегировать, наведение мыши/щелчок и т. д. Второй аргумент — это элемент, который мы хотим, чтобы событие срабатывало при возникновении события. Третий аргумент — это функция обратного вызова, которая запускается при возникновении события.

$(document).on('event', 'elementIdentifier', function(){
    //your code
});
person Ohgodwhy    schedule 23.07.2013
comment
jsfiddle - идеальная иллюстрация @Ian - person Jack; 18.08.2015

$(".parent-div").on("click", ".child-div-class-name" ,function(){
  somefunction();
});

все новые вставленные элементы внутри .parent-div будут иметь слушателей onclick

person anyavacy    schedule 22.03.2017

В дополнение к ответу Популуса, который сам по себе великолепен, логически эквивалентным решением для его второго варианта будет использование Обещания:

     var iGotYou = new Promise(function (res, rej) {
        $.ajax({
             //ajax paramaters
        })
            .done(function( data ) {
                //handle the data as necessary...
                //then resolve the Promise
                res();
            });
    });

    //the Promise has been resolved
    iGotYou.then(function (response) {
        //add the event listener now that the promise has been fulfilled
       document.getElementById('someId').addEventListener('click', function (e) {
        //whatever you want to do on click event
       });
    })
person Kal    schedule 21.08.2017

Я не совсем уверен, о чем вы здесь спрашиваете, но вы можете использовать функцию jQuery .on() для привязки к элементам, которые уже существуют в вашем документе, ИЛИ к элементам, которые будут существовать в будущем.

Вот краткий пример:

$(document).ready(function () {
    $(document).on('click', '#new-button', function() {
        alert("You clicked the new button");
    });

    //get some HTML via ajax. Let's assume you're getting <button id="new-button">Click me</button>
    $.get('url', function(res) {
        $('body').append(res);
    });
});
person Jedediah    schedule 23.07.2013