[英]Add event listener for each element in snapshot Firestore
I have the following code that gets a snapshot
from my Firestore collection called banner
.我有以下代码从名为
banner
Firestore 集合中获取snapshot
。 Each object has the following structure每个对象具有以下结构
{
index: // each object has index
image: // url of source image
link: // link to be redirected when clicked the image
}
Here is the HTML code where I dynamically add elements to HTML from my collection, I have 5
images in this case这是我从我的集合动态添加元素到 HTML 的 HTML 代码,在这种情况下我有
5
图像
<div id="homepage-background" class="background">
<img class="bg" src="https://firebasestorage.googleapis.com/v0/b....">
<img class="bg" src="https://firebasestorage.googleapis.com/v0/b....">
<img class="bg" src="https://firebasestorage.googleapis.com/v0/b....">
<img class="bg" src="https://firebasestorage.googleapis.com/v0/b....">
<img class="bg" src="https://firebasestorage.googleapis.com/v0/b....">
</div>
And here is the function这是功能
let homepageBackground = document.getElementById("homepage-background");
firebase
.firestore()
.collection("banner")
.orderBy("index")
.get()
.then((snapshot) => {
let array = snapshot.docs;
for (let i = 0; i < array.length; i++) {
console.log(array[i].data());
console.log("i before " + i);
let imgBackground = document.createElement("img");
imgBackground.setAttribute("class", "bg");
imgBackground.setAttribute("src", array[i].image);
imgBackground.setAttribute("data-index", i);
console.log("i after " + i);
imgBackground.addEventListener("click", function () {
const alertText = imgBackground.getAttribute("data-index");
alert(alertText);
});
homepageBackground.appendChild(imgBackground);
}
})
.catch((error) => {
console.log(error);
});
The problem is the each image I click, it alerts 5
, the index of the last element in my collection.问题是我点击的每张图片,它都会提醒
5
,这是我收藏中最后一个元素的索引。 I expect that when I click on the first picture to get an alert with 1
, click on second picture, get an alert of 2
and so on until the fifth picture to get an alert of 5
.我希望,当我在第一个点击图片以得到一个警报
1
,点击第二张照片,得到一个警报2
,以此类推,直到第五图片获得的警报5
。 Somehow that index
attribute of each document from collection is not displayed correctly since no matter picture I click, I get an alert of 5
, index of the last element.不知何故,集合中每个文档的
index
属性没有正确显示,因为无论我点击图片,我都会收到5
的警报,即最后一个元素的索引。 I believe the problem is with addEventListener()
function that might have been assigned only to the last HTML element because it always displays 5
.我认为问题在于
addEventListener()
函数可能只分配给最后一个 HTML 元素,因为它总是显示5
。
I am not quite sure why is it not working and what should I do to fix.我不太确定为什么它不起作用,我应该怎么做才能解决。
EDIT编辑
I have added 2 console logs, before and after imgBackground.setAttribute("data-index", i);
我在
imgBackground.setAttribute("data-index", i);
之前和之后添加了 2 个控制台日志imgBackground.setAttribute("data-index", i);
and it displays the following once the page is loaded一旦页面加载,它会显示以下内容
i before 0
i after 0
i before 1
i after 1
i before 2
i after 2
i before 3
i after 3
i before 4
i after 4
My assumption is that all images are already rendered to the HTML since they are displayed correctly to the screen.我的假设是所有图像都已呈现为 HTML,因为它们已正确显示在屏幕上。 But only that after the loop
i
was set last index.但只有在循环之后
i
才被设置为最后一个索引。 I have to mention that I have one more script file that is responsible for sliding the images in the page.不得不提的是,我还有一个脚本文件负责在页面中滑动图像。 It is just a
setInterval()
that runs every 5 seconds and adds show
class to each img
from that div
.它只是一个每 5 秒运行一次的
setInterval()
并将show
类添加到该div
每个img
。 The following is the script.以下是脚本。
document.addEventListener(
"load",
function () {
let slider = document.querySelector(".slider");
let buttons = document.querySelectorAll(".btn");
let slides = document.querySelectorAll(".img");
let backgrounds = document.querySelectorAll(".bg");
let options = document.querySelectorAll(".option");
let element = document.getElementById("homepage-background");
let numberOfChildren = element.getElementsByTagName("img").length;
let index = 1;
let op_index = 0;
let size = slides[index].clientWidth;
update();
function update() {
slider.style.transform = "translateX(" + -size * index + "px)";
backgrounds.forEach((img) => img.classList.remove("show"));
backgrounds[op_index].classList.add("show");
options.forEach((op) => op.classList.remove("colored"));
options[op_index].classList.add("colored");
}
function slide() {
slider.style.transition = "transform .5s ease-in-out";
update();
}
function btnCheck() {
if (this.id === "prev") {
index--;
if (op_index === 0) {
op_index = numberOfChildren - 1;
} else {
op_index--;
}
} else {
index++;
if (op_index === numberOfChildren - 1) {
op_index = 0;
} else {
op_index++;
}
}
slide();
}
slider.addEventListener("transitionend", () => {
if (index >= numberOfChildren - 1) {
return;
}
if (index <= 0) {
return;
}
if (slides[index].id === "fist") {
slider.style.transition = "none";
index = slides.length - 2;
slider.style.transform = "translateX(" + -size * index + "px)";
} else if (slides[index].id === "last") {
slider.style.transition = "none";
index = 1;
slider.style.transform = "translateX(" + -size * index + "px)";
}
});
buttons.forEach((btn) => btn.addEventListener("click", btnCheck));
options.forEach((option) => option.addEventListener("click", optionFunc));
setInterval(btnCheck, 5000);
},
5000
);
By the time the page renders, the loop has terminated and i == 5
, which is why your test alert always shows 5.到页面呈现时,循环已终止并且
i == 5
,这就是为什么您的测试警报始终显示 5。
I agree with @Marc that you should associate the element with its index and store it somewhere inside the loop.我同意@Marc 的观点,即您应该将元素与其索引相关联并将其存储在循环内的某个位置。
...
for (let i = 0; i < array.length; i++) {
...
// SET attribute "data-index"
imgBackground.setAttribute("data-index", i) // or array[i].data().index, which appears to be the same thing based on your description
imgBackground.addEventListener("click", function () {
// GET attribute "data-index"
const alertText = imgBackground.getAttribute('data-index')
alert(alertText);
...
});
...
}
...
Tested in developer console and working.在开发人员控制台中测试并正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.