【问题标题】:JavaScript onclick event gets the wrong id from dynamically generated html elementJavaScript onclick 事件从动态生成的 html 元素中获取错误的 id
【发布时间】:2020-03-02 03:05:23
【问题描述】:

在 NodeJS 应用程序中使用 mongodb 和 ejs,我创建了一个函数,该函数循环遍历购物车中的产品,并在页面上的表格内动态显示它们中的每一个。

我正在尝试创建一个数量更新函数,它使用一个输入字段来获取数量和一个按钮来更新数据库。

我的 HTML:

<tbody class="product-container">
    <!-- loop through each product -->
    <%  products.forEach (function(element) { %>
        <tr valign="top" class="cart-p-list">
            <!-- get individual unique ID for each product -->
            <input type="hidden" class="id" value="<%= element.item._id %>">

            <td class="col-qty cart-p-qty nowrap" align="right">
                <div class="proopc-input-append">
                    <!-- input for quantity and update button -->
                    <input type="number" class="input-ultra-mini proopc-qty-input qty" size="1" maxlength="4" name="quantity" value="<%= element.qty %>" data-quantity="<%= element.qty %>" step="1" min="1" max="50">
                    <button class="proopc-btn proopc-task-updateqty updateproduct" name="updatecart.0" title="Update Quantity In Cart"><i class="proopc-icon-refresh"></i></button>
                </div>
            </td>
        </tr>
        <% }); %>

出于测试目的,javascript 位于页面底部的&lt;script&gt; 标记中。

我的 JavaScript 代码:

window.addEventListener('load', function() {
    {
        // Update Quantity of product in shopping cart
        const block = document.querySelector('.product-container');


        block.addEventListener('click', function(e) {
            if (e.target.classList.contains('updateproduct')) {
                console.log(e);

                let id = e.target.parentNode.parentNode.parentNode.parentNode.querySelector('.id').value;
                let qty = +e.target.parentNode.querySelector('.qty').value;
                console.log(id);

                fetch(`/update/${id}/${qty}`, {
                    method: 'GET'
                }).then((res) => res.text());
            }
        });
    }
});

代码从我的 cart.js 获取以下 GET 请求:

router.get('/update/:id/:qty', function (req, res, next) {
    let productId = req.params.id;
    let quantity = +req.params.qty;

    let cart = new Cart(req.session.cart ? req.session.cart : {});
    cart.update(productId, quantity);
    req.session.cart = cart;
    res.redirect('back');
});

还有我的购物车模型:

module.exports = function Cart(oldCart) {
    this.items = oldCart.items || {};
    this.totalQty = oldCart.totalQty || 0;
    this.totalPrice = oldCart.totalPrice || 0;

    this.update = function (id, quantity) {
        let currentQuantity = this.items[id].qty;
        let newQuantity = this.items[id].qty = quantity;
        let currentPrice = this.items[id].price;
        let newPrice = this.items[id].item.price * quantity;;
        this.items[id].price = this.items[id].item.price * quantity;
        this.totalQty -= currentQuantity;
        this.totalQty += newQuantity;
        this.totalPrice -= currentPrice;
        this.totalPrice += newPrice;

    };

    this.generateArray = function () {
        let arr = [];
        for (let id in this.items) {
            arr.push(this.items[id]);
        }
        return arr;
    };
};

逻辑工作正常。产品正在更新中,价格和数量是正确的。总价和数量也是正确的。

但是,如果我在购物车中有多个产品(两种不同的产品),如果我尝试更新第二个产品(或任何不是第一个产品)的数量,在刷新时,而是更新第一个产品。

这是因为更新数量的事件监听器总是采用页面上第一个动态生成的项目的 id,而不是我尝试更新数量的那个。

这一定是因为循环遍历 ejs 文件中的产品造成的,所以我怀疑我需要在 js 函数中进行某种循环以获得正确的 id,但我不确定。

【问题讨论】:

  • 感谢您提供建议的答案。类“id”存在于每个动态生成的产品上。每个具有“id”类的输入都包含产品的正确唯一 ID。我不认为这是问题所在。
  • 查看此问题的答案。 stackoverflow.com/questions/34896106/… 应该可以帮到你。这也是console.log 命中吗?它的输出是什么?
  • 我按照您的建议尝试了前三个答案。结果是一样的。 console.log(e) 按原样输出事件。 MouseEvent {isTrusted: true, screenX: 866, screenY: 639, clientX: 866, clientY: 536, …}
  • 您建议的解决方案是,如果由于在创建动态元素之前执行代码而找不到该类,这不是问题。它总是选择第一个生成元素的 id,而不是选择的元素的 id 进行更新。
  • 找到了解决方案。无论如何,谢谢你的帮助,@yoshinator

标签: javascript html node.js express ejs


【解决方案1】:

我想出了一个解决办法。

我创建了一个函数,用于检查声明了更新请求的父级(tbody 在我的情况下为 product-container)的子级(在本例中为 tr)的位置。

这是找到索引的循环:

for (let i = 0, len = block.children.length; i < len; i++) {

    (function(index) {
        block.children[i].onclick = function() {
            console.log(index);
        }
    })(i);
}

这就是我在代码中实现它的方式:

document.addEventListener('DOMContentLoaded', function() {
    {
        // Update Quantity of product in shopping cart
        const block = document.querySelector('.product-container');
        // Fetch an array of all ids
        let ids = document.querySelectorAll('.id');
        // Create a function that shows the index of the child of the parent block
        for (let i = 0, len = block.children.length; i < len; i++) {
            (function(index) {
                block.children[i].onclick = function(e) {
                    if (e.target && e.target.classList.contains('updateproduct')) {
                        // ID now equals the id of the clicked child of the container
                        let id = ids[index].value;
                        let qty = +e.target.parentNode.querySelector('.qty').value;

                        fetch(`/update/${id}/${qty}`, {
                            method: 'GET'
                        }).then((res) => res.text()).then(() => window.history.go());
                    }
                }
            })(i);
        }
    }
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 1970-01-01
    • 2014-01-19
    • 2023-01-14
    • 2016-10-04
    • 1970-01-01
    • 2012-10-19
    相关资源
    最近更新 更多