javascript - Попытка добавить внутренний HTML, а затем нажмите на него не работает - PullRequest
0 голосов
/ 07 мая 2018

Я пытаюсь добавить внутренний html к элементу div, а затем динамически добавить к нему событие click. Предупреждает 1, но не 2:

alert(wordsGeneral.length); //prints 9
for (var i = 0; i < wordsGeneral.length; i++)
{
    var word = wordsGeneral[i];
    if (wordsToCorrect[word]!= undefined)
    {

        document.getElementById("text").innerHTML += "<u id=\"" + i + "\" style=\"text-decoration: underline;text-decoration-color: red;\">" + word + "</u>";
        alert("1");
        document.getElementById(i).addEventListener("click", function () {
            alert("2");
        });
    }
}

Может кто-нибудь помочь?

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Каждый раз, когда вы присваиваете innerHTML контейнера, любые ссылки Javascript на элементы внутри контейнера уничтожаются.Когда вы делаете something.innerHTML +=, интерпретатор делает что-то вроде:

(1) Извлекает текущий innerHTML контейнера в виде строки

(2) Очищает содержимое контейнера

(3) Объединяет строку с тем, что вы добавили

(4) Присваивает внутреннему HTML контейнера новую строку

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

Существует как минимум два хороших решения для такого рода вещей:

  • Недобавлять строки HTML, особенно когда имеешь дело с пользовательским вводом.Вместо этого создайте элементы и добавьте их в контейнер:

const text = document.querySelector('#text');
const wordsGeneral = ['foo', 'bar', 'baz'];
for (let i = 0; i < wordsGeneral.length; i++) {
  const word = wordsGeneral[i];
  text.insertAdjacentHTML('beforeend', "<u id=\"" + i + "\" style=\"text-decoration: underline;text-decoration-color: red;\">" + word + "</u>");
  document.getElementById(i).addEventListener("click", function() {
    alert("2");
  });
}
<div id="text"></div>

Другой метод заключается в использовании метода appendAdjacentHTML, который предназначен для такого рода вещей и не разыменовывает другие элементы в контейнере:

const text = document.querySelector('#text');
const wordsGeneral = ['foo', 'bar', 'baz'];
for (let i = 0; i < wordsGeneral.length; i++) {
  var word = wordsGeneral[i];
  const u = text.appendChild(document.createElement('u'));
  u.id = i;
  u.style.cssText = 'text-decoration: underline;text-decoration-color: red;';
  u.textContent = word;
  u.addEventListener("click", function() {
    alert("2");
  });
}
<div id="text"></div>
0 голосов
/ 07 мая 2018

Кажется, работает просто отлично:

i = 1;
word = i;
document.getElementById("text").innerHTML += "<u id=\""+i+"\" style=\"text-decoration: underline;text-decoration-color: red;\">" + word + "</u>";
alert("1");
document.getElementById(i).addEventListener("click", function () {
    alert("2");
});
<div id="text"/>

Я бы предположил , что вы не используете HTML5 и что i - это число, которое в HTML4 недопустимо:

Жетоны ID и NAME должны начинаться с буквы ([A-Za-z]) и могут сопровождаться любым количеством букв, цифр ([0-9]), дефисов ("-"), подчеркиваний (" _ "), двоеточия (": ") и точки (". ").

...