gpt4 book ai didi

循环中的 JavaScript addEventListener

转载 作者:行者123 更新时间:2023-11-30 16:15:52 24 4
gpt4 key购买 nike

我正在努力完成 Udacity 的 JavaScript Design Patterns course .其中一个练习项目是创建一个包含几张猫照片的页面。每张照片都有自己的标题和计数器,指示每张照片被点击的次数。我开始时将所有内容都硬编码在 html 中,但我现在正试图通过从 JavaScript 生成大部分页面来使其更通用且更易于更新。我已经能够显示所有文本和图像,并且在单击第二张图像时它的计数器会增加,但我无法弄清楚为什么第一张图像没有更新其计数器。单击它似乎甚至不会触发“单击”EventListener。

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);
}())
}

我制作了一个包含两个 cat 对象的数组,在我的 html 中获取对 div 的引用,定义更新 spanincreaseCount 函数> 包含给定猫照片的点击次数,然后循环遍历我数组中的每个猫对象,为它们的标题、图像和计数器生成 html,然后添加一个事件监听器以指示何时单击它们的图像。

第二张图片按预期工作,但第一张图片甚至没有触发事件监听器。我认为这可能与 closure 有关,但我已将循环中的所有内容包装在一个函数中。

更新

根据 Pointy 的建议,我按如下方式更新了循环,并且它按预期工作。我还按照建议将 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));
}

最佳答案

有几件事。

首先你需要传入i给函数:

(function (i) {
var currCat = cats[i];
...
}(i));

但是第二点比较棘手。您正在动态创建元素并尝试将事件监听器附加到它们,但这是行不通的。您需要利用的是事件委托(delegate) - 将事件监听器附加到父元素并捕获从附加元素冒出的事件。

需要对您的代码进行一些更改才能使其正常工作。

1) 向图像元素添加几个数据属性以引用猫的索引和猫名:

<img data-name="' + currCat.name + '" data-index="' + i + '" + id="' + currCat.name + '-photo" src="' + currCat.photo + '">

2) 在 catDiv 元素上创建新的事件监听器,从被点击元素的数据集中获取值,将这些值传递给 inceaseCount

catDiv.addEventListener('click', function(e) {
if (e.target && e.target.nodeName == "IMG") {
var data = e.target.dataset;
increaseCount(data.index, data.name + '-count');
}
});

3) 重写 increaseCount 函数以解决这些变化。

function increaseCount(index, span) {
cats[index].count++;
document.getElementById(span).innerHTML = cats[index].count;
}

Working example

关于循环中的 JavaScript addEventListener,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35537917/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com