简体   繁体   English

数组迭代过程中的addEventListener问题[已解决]

[英]addEventListener problem during Iteration of an array[solved]

i'm building a project for my boot camp, and i'm stuck in a small quite annoying area.我正在为我的新兵训练营建立一个项目,但我被困在一个很烦人的小地方。 i have an api where i can make queries to amazon and display products, each product has its own "card" styling and along with it i push each product to an empty array inside the user class constructor if the user select that he wants to add that product to his "profile", within the user class i have a function called "displayProducts" which basically iterating over that products array, creating a div element, modifying the innerHTML of the element on each iteration and displaying it on the page.我有一个 api,我可以在其中查询 amazon 并显示产品,每个产品都有自己的“卡片”样式,如果用户选择他想要添加,我会将每个产品推送到用户类构造函数中的空数组将该产品添加到他的“配置文件”,在用户类中,我有一个名为“displayProducts”的函数,它基本上迭代该产品数组,创建一个 div 元素,在每次迭代时修改元素的 innerHTML 并将其显示在页面上。 this is the function:这是功能:

        const productSection = document.getElementById('userProducts')
        productSection.innerHTML = ``;
        let div = document.createElement('div')
        if (user.products.length > 0) {
            user.products.forEach((product) => {
                div.innerHTML += `
        <div class="card horizontal">
            <div class="card-image">
                <img src=${product.img}>
            </div>

            <div class="card-stacked">
                <div class = "card-content">
                <span class = "card-title"> ${product.title} </span> 
                <p> ${product.rating} rating, ${product.totalReviews} reviews </p>
                <span> Price:${product.price}</span>
            </div>

            <div class="card-action">
                <button class="btn delete-${product.asin}">delete</button> 
            </div>

        </div> 
        `
                deleteButton = div.querySelector(`.delete-${product.asin}`).addEventListener('click', user.delete.bind(product))
                productSection.appendChild(div);
            }

The problem is, while adding the event listener to each button - it's af it's only applying the event listener to the last product, even though on each stage it select the correct button, i have been at it for over two hours and i'm quite lost.问题是,在向每个按钮添加事件侦听器时 - 它只是将事件侦听器应用于最后一个产品,即使在每个阶段它都选择了正确的按钮,我已经使用了两个多小时,我很失落。 How do i persist an event listener to each product card?我如何将事件侦听器持久化到每个产品卡?

When you use container.innerHTML += , any existing listeners inside the container will be lost, since the container's contents get re-parsed from the beginning from the new HTML string.当您使用container.innerHTML += ,容器内的任何现有侦听器都将丢失,因为容器的内容会从新的 HTML 字符串开始重新解析。 An alternative is to use insertAdjacentHTML , which does not corrupt existing elements:另一种方法是使用insertAdjacentHTML ,它不会破坏现有元素:

div.insertAdjacentHTML('beforeend', `
  <div class="card horizontal">
    <div class="card-image">
        <img src=${product.img}>
  // etc

Then using addEventListener inside the loop will work.然后在循环内使用addEventListener将起作用。

But another issue I'm concerned with is your concatenation of the HTML string with the products data.但我关心的另一个问题是 HTML 字符串与products数据的连接。 Unless this data is trustworthy, your current code can result in arbitrary code execution, which is a security risk.除非这些数据值得信赖,否则您当前的代码可能会导致任意代码执行,这是一种安全风险。 Instead of interpolating inside the template literal directly.而不是直接在模板文字内插值。 consider selecting the elements afterwards and assigning to their textContent (or other attribute) instead.考虑之后选择元素并分配给它们的textContent (或其他属性)。 For example, instead of:例如,而不是:

<img src=${product.img}>

append the current <div> , then assign to the src later.追加当前<div> ,然后分配给src稍后。 Instead of insertAdjacentHTML :而不是insertAdjacentHTML

const thisCard = div.appendChild(document.createElement('div'));
thisCard.className = 'card horizontal';
thisCard.innerHTML = `
    <div class="card-image">
        <img>
    </div>
    // etc
`;
thisCard.querySelector('img').src = product.img;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM