【问题标题】:producing a cart array upon "add to cart" click on product在“添加到购物车”点击产品时生成购物车数组
【发布时间】:2020-12-07 19:10:12
【问题描述】:

我目前正在构建这个小型购物车项目,但是,当我将产品传递给购物车类时,发生了一些奇怪的事情......

当我对购物车类中的产品列表进行 console.log() 时,我会为每个产品获取单独的数组。因此,例如,如果我从一个产品中添加 3 个产品,它们将存储在一个单独的数组中,请参见下面的屏幕截图:

注意:请注意,我每次点击一个,我希望只有一个数组包含我添加到购物车的所有产品。

查看下面的代码,包括其中涉及的所有类。

如控制台所示:

(3) [{…}, {…}, {…}]
0: {id: 1, productName: "Strawberry Basil", productImgURL: "https://cdn.shopify.com/s/files/1/0274/3641/7123/p…rry_Pop_Still_4K_Front-CherryPop.png?v=1588713373", type: Array(3), price: 7}
1: {id: 1, productName: "Strawberry Basil", productImgURL: "https://cdn.shopify.com/s/files/1/0274/3641/7123/p…rry_Pop_Still_4K_Front-CherryPop.png?v=1588713373", type: Array(3), price: 7}
2: {id: 1, productName: "Strawberry Basil", productImgURL: "https://cdn.shopify.com/s/files/1/0274/3641/7123/p…rry_Pop_Still_4K_Front-CherryPop.png?v=1588713373", type: Array(3), price: 7}
length: 3
__proto__: Array(0)
app.js:151 

(3) [{…}, {…}, {…}]
0: {id: 2, productName: "Sour Blueberry", productImgURL: "https://cdn.shopify.com/s/files/1/0274/3641/7123/p…rry_Still_4K_Front-SourBlueberry.png?v=1588713584", type: Array(2), price: 7}
1: {id: 2, productName: "Sour Blueberry", productImgURL: "https://cdn.shopify.com/s/files/1/0274/3641/7123/p…rry_Still_4K_Front-SourBlueberry.png?v=1588713584", type: Array(2), price: 7}
2: {id: 2, productName: "Sour Blueberry", productImgURL: "https://cdn.shopify.com/s/files/1/0274/3641/7123/p…rry_Still_4K_Front-SourBlueberry.png?v=1588713584", type: Array(2), price: 7}
length: 3
__proto__: Array(0)

// local Item List for development
const products = [{
    id: 1,
    productName: 'Strawberry Basil',
    productImgURL: 'https://cdn.shopify.com/s/files/1/0274/3641/7123/products/Cherry_Pop_Still_4K_Front-CherryPop.png?v=1588713373',
    type: ['berry', 'citrusy', 'fancy'],
    price: 7,
  },
  {
    id: 2,
    productName: 'Sour Blueberry',
    productImgURL: 'https://cdn.shopify.com/s/files/1/0274/3641/7123/products/SourBlueBerry_Still_4K_Front-SourBlueberry.png?v=1588713584',
    type: ['sour', 'berry'],
    price: 7,
  },
  {
    id: 3,
    productName: 'Blackberry Jam',
    productImgURL: 'https://cdn.shopify.com/s/files/1/0274/3641/7123/products/BlackBerry_Jam_Still_4K_Front-BlackberryJam.png?v=1595035965',
    type: ['berry'],
    price: 7,
  }
];

class SideCartDrawer {
  cartProducts = [];

  addToCart(product) {
    this.cartProducts.push(product);
    console.log(this.cartProducts);
    const productEl = document.createElement('div');
    productEl.textContent = 'product 1';
  }

  renderCart() {
    let cartEl = document.createElement('h2');
    cartEl.id = 'cart-list-empty';
    cartEl.textContent = 'Cart is Empty';

    return cartEl;
  }
}

//Single product rendering

class SingleProductRendering extends SideCartDrawer {
  constructor(productDetails) {
    super();
    this.product = productDetails;
    this.productElementTemplate = document.getElementById('item-main-template');
  }

  addProductToCart = () => {
    this.addToCart(this.product);
  };

  render() {
    const productTemplateEl = document.importNode(
      this.productElementTemplate.content,
      true
    );
    const productEl = productTemplateEl.querySelector('.single-product');
    productEl.id = this.product.id;
    productEl.querySelector('img').src = this.product.productImgURL;
    productEl.querySelector('h2').textContent = this.product.productName;

    const btn = productEl.querySelector('button');
    btn.addEventListener('click', () => {
      this.addProductToCart();
    });

    return productEl;
  }
}

//Product List Rendering

class ProductList {
  constructor() {
    this.fetchProducts();
  }

  fetchProducts() {
    this.products = products;
  }

  render() {
    const productListEl = document.createElement('section');
    productListEl.className = 'products-holder';
    productListEl.id = 'product-holder';
    for (let product of this.products) {
      const productEl = new SingleProductRendering(product);
      const productElRendered = productEl.render();
      productListEl.append(productElRendered);
    }

    return productListEl;
  }
}

//shop API - assemble

class Shop {
  render() {
    const renderHookProductList = document.getElementById('app');
    const cartHook = document.getElementById('cart-items-list');
    const productList = new ProductList();
    const productListRendered = productList.render();
    renderHookProductList.append(productListRendered);

    const cartItemDrawer = new SideCartDrawer();
    const cartDrawer = cartItemDrawer.renderCart();
    cartHook.append(cartDrawer);
  }
}

const shop = new Shop();
shop.render();
<body>
  <template id="item-main-template">
            <article class="single-product">
                <div class="product-image-container">
                    <img class="tour-img" src="" alt="" />
                </div>
                <div class="product-title">
                    <h2></h2>
                </div>
                <div class="cart-btn-holder">
                    <button class="add-to-cart-btn" id="add-to-cart">add to cart</button>
                </div>
            </article>
        </template>
  <template id="item-cart-template">
            <article class="cart-item">
                <div class="side-cart-product-item">
                    <h3>product 1</h3>
                    <button class="trash-icon">
                        <i class="far fa-trash-alt"></i>
                    </button>
                </div>
                <div class="side-cart-product-price">
                    <p>$40</p>
                    <div class="cart-qty">
                        <button class="qty-btn">-</button>
                        <span>0</span>
                        <button class="qty-btn">+</button>
                    </div>
                </div>
            </article>
        </template>

  <header id="home">
    <nav>
      <button type="button" class="nav-toggle" id="nav-toggle">
                    <i class="fas fa-bars"></i>
                </button>
      <h1 class="header-title">RAINBOW SODAS UK</h1>
      <button type="button" class="nav-toggle" id="cart-drawer-open">
                    <i class="fas fa-shopping-cart"
                        ><span class="cart-items-counter">0</span></i
                    >
                </button>
    </nav>
  </header>
  <main>
    <div class="side-menu" id="side-menu">
      <button type="button" id="drawer-close" class="drawer-menu-close">
                    <i class="far fa-window-close"></i>
                </button>
      <div class="drawer-title">SODAS UK</div>
      <ul class="nav-links">
        <li>
          <a href="#products-filter" class="nav-link">shop all</a>
        </li>
        <li>
          <a href="#products-filter" class="nav-link">products</a>
        </li>
        <li>
          <a href="#about" class="nav-link">about us</a>
        </li>
      </ul>
    </div>
    <div class="cart-drawer" id="side-cart">
      <div class="cart-inner">
        <button type="button" id="cart-drawer-close" class="cart-drawer-close">
                        <i class="far fa-window-close"></i>
                    </button>
        <div class="cart-drawer-title">CART</div>
        <section class="cart-items-list" id="cart-items-list"></section>
      </div>
      <div class="cart-footer">
        <div class="total-display-side-cart">
          <h3>total</h3>
          <span>0</span>
        </div>
        <button class="checkout-drawer">checkout</button>
      </div>
    </div>
    <div id="app"></div>
  </main>
</body>

【问题讨论】:

  • 请将屏幕截图中隐藏的数据显示为文本。盲人、屏幕阅读器、搜索引擎和其他人无法阅读图像中的文本。最好的办法是你可以使用console.log(JSON.stringify(arr, null, 2)) 并粘贴结果,因为浏览器往往会给控制台添加很多麻烦。
  • 我给你做了一个sn-p。请减少项目并添加相关的 HTML 和 CSS 以提供minimal reproducible example
  • @mplungjan 不确定您为什么需要 HTML 和 CSS 类。这主要是javascript代码的问题?
  • 我需要它来不必用 EYEBALL 调试你的代码!
  • 啊! @mplungjan 我已经添加了 html!抱歉,我对编码很陌生,刚刚学习

标签: javascript html oop


【解决方案1】:

您需要查看购物车是否已经有产品

addToCart(product) {
  const cartProduct = this.cartProducts.find(item => item.id === product.id);
  if (cartProduct) {
    cartProduct.qty++
    }  
  else {
    product.qty = 1;
    this.cartProducts.push(product);
  }  
  console.log(this.cartProducts)
  const productEl = document.createElement('div');
  productEl.textContent = 'product 1';
}

// local Item List for development
const products = [{
    id: 1,
    productName: 'Strawberry Basil',
    productImgURL: 'https://cdn.shopify.com/s/files/1/0274/3641/7123/products/Cherry_Pop_Still_4K_Front-CherryPop.png?v=1588713373',
    type: ['berry', 'citrusy', 'fancy'],
    price: 7,
  },
  {
    id: 2,
    productName: 'Sour Blueberry',
    productImgURL: 'https://cdn.shopify.com/s/files/1/0274/3641/7123/products/SourBlueBerry_Still_4K_Front-SourBlueberry.png?v=1588713584',
    type: ['sour', 'berry'],
    price: 7,
  },
  {
    id: 3,
    productName: 'Blackberry Jam',
    productImgURL: 'https://cdn.shopify.com/s/files/1/0274/3641/7123/products/BlackBerry_Jam_Still_4K_Front-BlackberryJam.png?v=1595035965',
    type: ['berry'],
    price: 7,
  }
];

class SideCartDrawer {
  cartProducts = [];

  addToCart(product) {
    const cartProduct = this.cartProducts.find(item => item.id === product.id);
    if (cartProduct) {
      cartProduct.qty++
    }  
    else {
      product.qty = 1;
      this.cartProducts.push(product);
    }  
    console.log(this.cartProducts)
    const productEl = document.createElement('div');
    productEl.textContent = 'product 1';
  }

  renderCart() {
    let cartEl = document.createElement('h2');
    cartEl.id = 'cart-list-empty';
    cartEl.textContent = 'Cart is Empty';

    return cartEl;
  }
}

//Single product rendering

class SingleProductRendering extends SideCartDrawer {
  constructor(productDetails) {
    super();
    this.product = productDetails;
    this.productElementTemplate = document.getElementById('item-main-template');
  }

  addProductToCart = () => {
    this.addToCart(this.product);
  };

  render() {
    const productTemplateEl = document.importNode(
      this.productElementTemplate.content,
      true
    );
    const productEl = productTemplateEl.querySelector('.single-product');
    productEl.id = this.product.id;
    productEl.querySelector('img').src = this.product.productImgURL;
    productEl.querySelector('h2').textContent = this.product.productName;

    const btn = productEl.querySelector('button');
    btn.addEventListener('click', () => {
      this.addProductToCart();
    });

    return productEl;
  }
}

//Product List Rendering

class ProductList {
  constructor() {
    this.fetchProducts();
  }

  fetchProducts() {
    this.products = products;
  }

  render() {
    const productListEl = document.createElement('section');
    productListEl.className = 'products-holder';
    productListEl.id = 'product-holder';
    for (let product of this.products) {
      const productEl = new SingleProductRendering(product);
      const productElRendered = productEl.render();
      productListEl.append(productElRendered);
    }

    return productListEl;
  }
}

//shop API - assemble

class Shop {
  render() {
    const renderHookProductList = document.getElementById('app');
    const cartHook = document.getElementById('cart-items-list');
    const productList = new ProductList();
    const productListRendered = productList.render();
    renderHookProductList.append(productListRendered);

    const cartItemDrawer = new SideCartDrawer();
    const cartDrawer = cartItemDrawer.renderCart();
    cartHook.append(cartDrawer);
  }
}

const shop = new Shop();
shop.render();
<body>
  <template id="item-main-template">
            <article class="single-product">
                <div class="product-image-container">
                    <img class="tour-img" src="" alt="" />
                </div>
                <div class="product-title">
                    <h2></h2>
                </div>
                <div class="cart-btn-holder">
                    <button class="add-to-cart-btn" id="add-to-cart">add to cart</button>
                </div>
            </article>
        </template>
  <template id="item-cart-template">
            <article class="cart-item">
                <div class="side-cart-product-item">
                    <h3>product 1</h3>
                    <button class="trash-icon">
                        <i class="far fa-trash-alt"></i>
                    </button>
                </div>
                <div class="side-cart-product-price">
                    <p>$40</p>
                    <div class="cart-qty">
                        <button class="qty-btn">-</button>
                        <span>0</span>
                        <button class="qty-btn">+</button>
                    </div>
                </div>
            </article>
        </template>

  <header id="home">
    <nav>
      <button type="button" class="nav-toggle" id="nav-toggle">
                    <i class="fas fa-bars"></i>
                </button>
      <h1 class="header-title">RAINBOW SODAS UK</h1>
      <button type="button" class="nav-toggle" id="cart-drawer-open">
                    <i class="fas fa-shopping-cart"
                        ><span class="cart-items-counter">0</span></i
                    >
                </button>
    </nav>
  </header>
  <main>
    <div class="side-menu" id="side-menu">
      <button type="button" id="drawer-close" class="drawer-menu-close">
                    <i class="far fa-window-close"></i>
                </button>
      <div class="drawer-title">SODAS UK</div>
      <ul class="nav-links">
        <li>
          <a href="#products-filter" class="nav-link">shop all</a>
        </li>
        <li>
          <a href="#products-filter" class="nav-link">products</a>
        </li>
        <li>
          <a href="#about" class="nav-link">about us</a>
        </li>
      </ul>
    </div>
    <div class="cart-drawer" id="side-cart">
      <div class="cart-inner">
        <button type="button" id="cart-drawer-close" class="cart-drawer-close">
                        <i class="far fa-window-close"></i>
                    </button>
        <div class="cart-drawer-title">CART</div>
        <section class="cart-items-list" id="cart-items-list"></section>
      </div>
      <div class="cart-footer">
        <div class="total-display-side-cart">
          <h3>total</h3>
          <span>0</span>
        </div>
        <button class="checkout-drawer">checkout</button>
      </div>
    </div>
    <div id="app"></div>
  </main>
</body>

【讨论】:

  • 感谢您。数量有效,现在的问题是当我在 UI 中渲染这些项目时,它们都显示出来了。我的计划是只允许购物车抽屉中的每个渲染之一。你知道这是怎么做到的吗?数组一直显示为我最初的问题。我的想法是,如果我拥有所有项目(重复项且没有重复项),那么我可以应用一种方法让每个项目只有一个。
  • 我不明白你的意思。请逐步说明如何重新创建您看到的内容以及您的预期输出。
  • 当我将产品添加到购物车时,购物车数组 this.cartProducts 在控制台中显示如下:[product1] [product2] [product3],而不是 [product1, product2, product3]。如果我拥有所有产品,例如[product1, product 1, product 2, product 2] 然后我可以在渲染所有产品之前过滤掉重复项。这一刻,我做不到。
  • 我添加了一个关于这个stackoverflow.com/questions/65196894/…的新问题
  • 我设法通过将其添加到您创建的 if 语句中删除了子元素上的前一个子元素 if (cartProduct) { car​​tProduct.qty++; document.getElementById(cart-${product.id}).remove(); } 谢谢你的帮助顺便说一句
猜你喜欢
  • 2011-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-26
  • 1970-01-01
  • 1970-01-01
  • 2012-06-09
相关资源
最近更新 更多