Перехват событий кликов на элементах <a>, которые программно добавляются в DOM - PullRequest
3 голосов
/ 21 августа 2010

У меня есть обратный вызов AJAX, который возвращает список результатов, записанных в виде ссылок в конкретном div.Код выглядит примерно так:

$.each(data, function (idx, item) {
    var a = document.createElement("a");
    a.innerText = item.name;
    a.href = "#";
    // TODO set handler for click event
    d.appendChild(a);
    d.innerHTML += "<br/>";
});

Это отлично работает, и ссылки появляются.Тем не менее, я хочу выполнить некоторые действия, когда ссылки нажимаются.item имеет некоторые другие свойства, которые мне понадобятся в обработчике кликов, поэтому я хотел бы закрыть их.Вот определение обработчика:

    // defined in loop as a closure
    var clickHandler = function() {
        $('#siteId').value = item.siteId; // closed over this property
        $('#siteName').value = item.name; // and this one
        return false;
    };

Я пробовал несколько способов предоставления этого обработчика для события click.Во-первых:

    a.onclick = clickHandler;

Во-вторых:

    a.addEventListener("click", clickHandler, true);  

Я также пробовал mouseup, mousedown события, но они тоже не работают.

Я вижу, что браузер переходит на якорь # (он добавляется к URL).

Что здесь происходит?Кроме того, есть ли решение jQuery, которое было бы более надежным в браузерах?

Ответы [ 4 ]

2 голосов
/ 21 августа 2010
d.innerHTML += "<br/>";

Это твоя проблема. Никогда innerHTML+= ничего . Он выполняет сериализацию объектов документа в родительском элементе в HTML, добавляет строку и затем анализирует всю строку обратно в новые объекты DOM. Это медленно и теряет всю информацию, которая не может быть сохранена в сериализованной разметке HTML, например, значения полей, ссылки JS и обработчики событий . Таким образом, любой обработчик событий, добавленный вами в <a>, немедленно уничтожается следующей строкой.

HTML не является окончательным хранилищем данных страницы в браузере; Вы не можете редактировать это напрямую. Вы можете только сериализовать часть содержимого документа в новый HTML-код (который может немного отличаться от HTML-кода, введенного вами для анализа страницы) и выполнить синтаксический анализ HTML в совершенно новых объектах.

Поэтому вместо этого продолжайте использовать методы DOM:

d.appendChild(document.createElement('br'))

За исключением:

a.innerText = item.name;

Это расширение IE, которое не поддерживается везде. Вы можете использовать его как запасной вариант для IE, где стандартное свойство textContent не поддерживается, или, для максимальной совместимости, просто используйте старый document.createTextNode() и добавьте его к a.

Поскольку вы, похоже, используете jQuery, используйте text(), чтобы сделать это, и click(), чтобы связать событие, как в других ответах.

2 голосов
/ 21 августа 2010

Вы можете сделать что-то подобное, используя jQuery:

$.each(data, function (idx, item) {
  $("<a />", { text: item.name, href: '#', click: clickHandler })
     .appendTo(d).after('<br />');
});

При этом используется $(html, props) в качестве метода создания элемента, настройки его текста и href свойств, а также назначения обработчика щелчка при создании. После этого мы используем .appendTo(), чтобы добавить его к элементу d, затем добавляем <br /> после него, используя .after().

1 голос
/ 21 августа 2010

есть ли решение jQuery, которое было бы более надежным в браузерах?

Вы можете получить объект jQuery из существующего элемента DOM и затем связать обработчик щелчков стандартным способом:

$(a).click(clickHandler);

Кроме того, я подозреваю, что ваш обработчик кликов неверен. Если вы пытаетесь установить значение элемента, вы должны использовать метод val, а не присваивать свойству value:

var clickHandler = function() {
    $('#siteId').val(item.siteId); // closed over this property
    $('#siteName').val(item.name); // and this one
    return false;
};
0 голосов
/ 21 августа 2010

Используйте jQuery.live, чтобы прикрепить обработчик событий ко всем событиям, которые соответствуют селектору сейчас или в будущем.См. Документацию jQuery:

http://api.jquery.com/live/

Это правильно прикрепит обработчик, даже если элемент добавлен в DOM после определения обработчика события

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