Я пытаюсь работать через Udacity JavaScript Design Patterns course. Одним из практических проектов является создание страницы с несколькими фотографиями кошек. На каждой фотографии есть свой заголовок и счетчик, указывающий, сколько раз на каждую фотографию было нажато. Я начал с того, что все было жестко закодировано в html, но теперь я пытаюсь сделать его более простым и простым в обновлении, создав большую часть страницы из JavaScript. Я смог получить весь текст и изображения, чтобы показать, и у меня есть счетчик второго изображения, когда он нажимается, но я не могу понять, почему первое изображение не обновляет счетчик. Нажатие на нее даже не запускает «click» EventListener.JavaScript addEventListener в цикле
HTML:
<html>
<body>
<div id="cats"></div>
</body>
<script src="catclick.js"></script>
</html>
JS:
"use strict";
var cat1 = {};
cat1.photo = "cat.jpg";
cat1.name = "Whiskers";
cat1.count = 0;
var cat2 = {};
cat2.photo = "cat2.jpg";
cat2.name = "Socks";
cat2.count = 0;
var cats = [cat1, cat2];
var catDiv = document.getElementById('cats');
function increaseCount(cat, span) {
cat.count++;
span.innerHTML = cat.count;
}
for (var i=0; i<cats.length; i++) {
(function() {
var currCat = cats[i];
var existingHTML = catDiv.innerHTML;
var newHTML = '<h3>' + currCat.name + '</h3><img id="' + currCat.name + '-photo" src="' + currCat.photo + '">';
newHTML += '<p>' + currCat.name + ' has been clicked <span id="' + currCat.name + '-count">0</span> times.</p>';
catDiv.innerHTML = existingHTML + newHTML;
var photoObj = document.getElementById(currCat.name + "-photo");
var countSpan = document.getElementById(currCat.name + "-count");
photoObj.addEventListener('click', function(){increaseCount(currCat, countSpan);}, false);
}())
}
я сделать массив из двух кошки объектов, получить ссылку на DIV в моем HTML, определить функцию increaseCount
, которая обновляет span
, содержащий кол-во кликов данной фотографии, а затем цикл каждого объекта cat в моем массиве, генерирование html для их названия, изображения и счетчика перед добавлением прослушивателя событий, когда их изображение является кликом рунец.
Второе изображение работает так, как ожидалось, но первое не запускает прослушиватель событий. Я думал, что это может быть связано с closure, но я завернул все в цикл в функции.
Update
С предложением заостренные, я обновил петлю следующим образом, и он работает, как ожидалось. Я также добавил i
к функции, как было предложено, хотя я не уверен, что это действительно необходимо в этом случае.
for (var i=0; i<cats.length; i++) {
(function (i) {
var currCat = cats[i];
var newDiv = document.createElement("div"); // div for this cat
var catTitle = document.createElement("h3"); // cat name
catTitle.appendChild(document.createTextNode(currCat.name));
newDiv.appendChild(catTitle);
var catPhoto = document.createElement("img"); // cat photo
catPhoto.setAttribute("id", currCat.name + "-photo");
catPhoto.setAttribute("src", currCat.photo);
newDiv.appendChild(catPhoto);
var catPara = document.createElement("p"); // cat click count
var catSpan = document.createElement("span");
catSpan.setAttribute("id", currCat.name + "-count");
catSpan.appendChild(document.createTextNode("0"));
catPara.appendChild(document.createTextNode(currCat.name + " has been clicked "));
catPara.appendChild(catSpan);
catPara.appendChild(document.createTextNode(" times."));
newDiv.appendChild(catPara);
catDiv.appendChild(newDiv);
catPhoto.addEventListener('click', function(){increaseCount(currCat, catSpan);}, false);
}(i));
}
При установке '.innerHTML', даже если вы кладете обратно предыдущее содержимое вы проигрышные задания обработчиков событий. Назначения обработчика событий связаны с самими узлами DOM, и перезапись '.innerHTML' удаляет эту часть DOM и создает целое новое поддерево. – Pointy
Разделите его на два отдельных цикла: сначала создайте контент, а затем назначьте обработчики событий. Или создайте контент, добавив узлы DOM вместо перезаписывания DOM через '.innerHTML'. – Pointy
Спасибо, Поинты. – WhiteHotLoveTiger