如何在 JavaScript 中更新每个 SKU 的数量和总价?

问题描述 投票:0回答:1

我正在为一家虚构的在线商店开发购物车功能。此功能的核心是一个

Cart
类,用于管理信息并执行计算。该类不与 HTML 文档或 DOM 交互,它只是执行计算。

Cart
类具有管理产品的方法。每个产品都有一个 SKU、标题、价格属性,我也尝试添加一个数量属性,但我认为它不起作用。我有两个按钮,
addButton
subtractButton
,用于每种产品增加或减少数量。

我想实现以下目标:

  1. 单击
    addButton
    时,产品数量应增加 1,并且该 SKU 的总价格应在
    total-SKU
    范围内更新。
  2. 单击
    subtractButton
    时,产品数量应减少 1(如果大于 0),并且该 SKU 的总价应在
    total-SKU
    范围内更新。
  3. 所有 SKU 的总价应计算并显示在
    total
    div 中。

这是jsFiddle中的代码:https://jsfiddle.net/mlpz2/edfjLhb2

这是代码:

class Cart {
    constructor(products, currency) {
        this.products = [];
        this.currency = "";
    }
    initializeQuantity = () => {
        for (let product of this.products) {
          product.quantity = 0; // Initialize quantity to 0 for each product
        }
        console.log(this.products.quantity);
      };
    updateUnits = (sku, units) => {
        // Update the number of units to be purchased for a product
        let product = this.products.find((p) => p.sku === sku);
        if (product) {
            product.quantity = units;
            console.log(this.products.quantity);
        } else {
            this.products.push({ sku: sku, quantity: units });
        }
    };

    getProductInformation = (sku) => {
        // Returns the data of a product along with the selected units
        // For example:
        // {
        // "sku": "0K3QOSOV4V",
        // "quantity": 3
        // }
        return this.products.find((p) => p.sku === sku);
    };

    getAllProducts = () => {
        return this.products;
      };

    getCart = () => {
        // Returns information about the products added to the cart
        // Along with the calculated total of all products
        // For example:
        // {
        // "total": "5820",
        // "currency: "€",
        // "products" : [
        // {
        // "sku": "0K3QOSOV4V"
        // ..
        // }
        // ]}
        let total = this.products.reduce(
            (sum, p) => sum + p.quantity * p.price,
            0
        );
        return { total: total, currency: this.currency, products: this.products };
    };
}

let cart = new Cart();
cart.initializeQuantity();
const getProductsData = async () => {
    let response = await fetch(
        "https://jsonblob.com/api/jsonBlob/1241305513466912768"
    );
    let data = await response.json();
    console.log(data);
    return data; // return the full response
};

const showProducts = (products) => {
    console.log(products);
    
    let productsContainer = document.getElementById("productsContainer");
    for (let product of products) {
        let quantity = product.quantity || 0; // Initialize quantity here

        let productElement = document.createElement("div");
        productElement.innerHTML = `
                        <h2>${product.title}</h2>
                        <p>Ref: ${product.SKU}</p>
                        <p>Price: ${product.price}€/unit</p>
                        <button class="substractButton">-</button>
                        <span id="quantity-${product.SKU}">${quantity}</span>
                        <button class="addButton">+</button>
                        <p>Total: <span id="total-${product.SKU}">0</span>€</p>
                `;
        productElement.className = "product";
        productsContainer.appendChild(productElement);
        let addButtons = productElement.querySelectorAll(".addButton");
        for (let i = 0; i < addButtons.length; i++) {
            addButtons[i].addEventListener('click', () => updateQuantity(product.SKU, 1));
        }
        console.log(addButtons);
        let subtractButtons = productElement.querySelectorAll(".substractButton");
        for (let i = 0; i < subtractButtons.length; i++) {
            subtractButtons[i].addEventListener('click', () => updateQuantity(product.SKU, -1));
            console.log(typeof subtractButtons[i], subtractButtons[i]);
        }
    }
    console.log(productsContainer);
};


const updateTotal = (sku) => {
    let products = cart.getAllProducts(); // Assuming getCart returns an array of products
    let total = 0;
    console.log(products); // Check if the products are being fetched correctly

    for (let product of products) {
        total += product.quantity * product.price;
    }
    document.getElementById('total').textContent = `TOTAL: ${total}`; // Assuming 'total' is the id of the element displaying the total price
};

const updateQuantity = (sku, change) => {
    let product = cart.getProductInformation(sku);
    if (product) {
        product.quantity += change;
        if (product.quantity < 0) {
            // Ensure the quantity doesn't go below 0
            product.quantity = 0;
        }
        document.getElementById(`quantity-${sku}`).textContent = product.quantity;
        document.getElementById(`total-${sku}`).textContent =
            product.quantity * product.price;
        updateTotal();
    }
};

getProductsData().then((data) => {
    if (data && data.products) {
        cart.products = data.products;
        cart.products = data.products.map((product) => {
            return {
                ...product,
                price: parseFloat(product.price),
            };
        }); // assign the currency to the cart object
        showProducts(cart.products);
        updateTotal();
    } else {
        console.error("Failed to fetch products");
    }
});

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="styles.css">
</head>

<body>
    <div id="productsContainer">
        <div id="total">
            <!-- The total will be shown here -->
        </div>
    </div> 
<script src="script.js"></script>
</body>

</html>
#productsContainer {
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    margin-top: 20px;
    position: relative;
}

.product {
    width: 200px;
    margin: 10px;
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
    text-align: center;

}

#total {
    position: absolute;
    font-size: 20px;
    font-weight: bold;
    bottom: -20px;
    left: 10px;
    background-color: #ececec;
}

@media (min-width: 768px) {
    #productsContainer {
        flex-direction: row;
    }
}

产品是从 API 获取的。我正在使用 jsonblob.com(https://jsonblob.com/api/jsonBlob/1241305513466912768) 创建一个模拟 API。

{
  "currency": "€",
  "products": [
    {
      "SKU": "0K3QOSOV4V",
      "title": "iFhone 13 Pro",
      "price": "938.99"
    },
    {
      "SKU": "TGD5XORY1L",
      "title": "Cargador",
      "price": "49.99"
    },
    {
      "SKU": "IOKW9BQ9F3",
      "title": "Funda de piel",
      "price": "79.99"
    }
  ]
}

我想我不知道如何:

  1. 在 DOM 中为产品列表创建新元素。
  2. 监听事件以更新每个产品的单位数量。
  3. 每当发生更改时更新 DOM 中的总价。

我不确定如何为

addButton
subtractButton
创建事件监听器以及如何更新 DOM 中的数量和总价。

我也愿意接受任何改进代码的建议。任何帮助将不胜感激!

感谢您的阅读:)

javascript api dom event-listener shopping-cart
1个回答
0
投票

为所有按钮分别添加事件监听器,并检查带有 id 的事件以更新特定元素。

希望这有帮助。

class Cart {
    constructor(products, currency) {
        this.products = [];
        this.currency = "";
    }
    initializeQuantity = () => {
        for (let product of this.products) {
          product.quantity = 0; // Initialize quantity to 0 for each product
        }
        console.log(this.products.quantity);
      };
    updateUnits = (sku, units) => {
        // Update the number of units to be purchased for a product
        let product = this.products.find((p) => p.sku === sku);
        if (product) {
            product.quantity = units;
            console.log(this.products.quantity);
        } else {
            this.products.push({ sku: sku, quantity: units });
        }
    };

    getProductInformation = (sku) => {
        // Returns the data of a product along with the selected units
        // For example:
        // {
        // "sku": "0K3QOSOV4V",
        // "quantity": 3
        // }
        return this.products.find((p) => p.SKU === sku);
    };

    getAllProducts = () => {
        return this.products;
      };

    getCart = () => {
        // Returns information about the products added to the cart
        // Along with the calculated total of all products
        // For example:
        // {
        // "total": "5820",
        // "currency: "€",
        // "products" : [
        // {
        // "sku": "0K3QOSOV4V"
        // ..
        // }
        // ]}
        let total = this.products.reduce(
            (sum, p) => sum + p.quantity * p.price,
            0
        );
        return { total: total, currency: this.currency, products: this.products };
    };
}

let cart = new Cart();
cart.initializeQuantity();
const getProductsData = async () => {
    let response = await fetch(
        "https://jsonblob.com/api/jsonBlob/1241305513466912768"
    );
    let data = await response.json();
    console.log(data);
    return data; // return the full response
};

const showProducts = (products) => {
    console.log(products);
    
    let productsContainer = document.getElementById("productsContainer");
    for (let product of products) {
        let quantity = product.quantity || 0; // Initialize quantity here

        let productElement = document.createElement("div");
        productElement.innerHTML = `
                        <h2>${product.title}</h2>
                        <p>Ref: ${product.SKU}</p>
                        <p>Price: ${product.price}€/unit</p>
                        <button class="substractButton" id=${product.SKU}>-</button>
                        <span id="quantity-${product.SKU}">${quantity}</span>
                        <button class="addButton" id=${product.SKU}>+</button>
                        <p>Total: <span id="total-${product.SKU}">0</span>€</p>
                `;
        productElement.className = "product";
        productsContainer.appendChild(productElement);
        let addButtons = productElement.querySelectorAll(".addButton");
           addButtons.forEach(button => {
            button.addEventListener('click', event => {
                updateQuantity(event.target.id, 1);
            });
          });
        
        
        console.log(addButtons);
        let subtractButtons = productElement.querySelectorAll(".substractButton");
        
        subtractButtons.forEach(button => {
            button.addEventListener('click', event => {
                updateQuantity(event.target.id, -1);
                console.log(event.target);
            });
          });
    }
    console.log(productsContainer);
};


const updateTotal = (sku) => {
    let products = cart.getAllProducts(); // Assuming getCart returns an array of products
    let total = 0;
    console.log(products); // Check if the products are being fetched correctly

    for (let product of products) {
        total += product.quantity * product.price;
    }
    document.getElementById('total').textContent = `TOTAL: ${total}`; // Assuming 'total' is the id of the element displaying the total price
};

const updateQuantity = (sku, change) => {
    
    let product = cart.getProductInformation(sku);
    if (product) {
        if(!product.quantity){
            product.quantity = 0;
        }
        product.quantity += change;
        if (product.quantity < 0) {
            // Ensure the quantity doesn't go below 0
            product.quantity = 0;
        }
        document.getElementById(`quantity-${sku}`).textContent = product.quantity ;
        document.getElementById(`total-${sku}`).textContent =
            product.quantity * product.price;
        updateTotal();
    }
};

getProductsData().then((data) => {
    if (data && data.products) {
        cart.products = data.products;
        cart.products = data.products.map((product) => {
            return {
                ...product,
                price: parseFloat(product.price),
            };
        }); // assign the currency to the cart object
        showProducts(cart.products);
        updateTotal();
    } else {
        console.error("Failed to fetch products");
    }
});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="productsContainer">
        <div id="total">
            <!-- The total will be shown here -->
        </div>
    </div> 
    <script src="./product.js"></script>
</body>
</html>

© www.soinside.com 2019 - 2024. All rights reserved.