【问题标题】:How to fix a nesting forEach如何修复嵌套 forEach
【发布时间】:2021-09-01 04:17:50
【问题描述】:

我练习 DOM 操作(纯香草 JS),我需要检查所有价格,如果其中任何价格超过 3,00 英镑,则整个产品卡应将其背景颜色更改为红色。 由于某些未知原因,如果我只更改价格 div,代码运行良好,但是,当我尝试定位整张卡片时,它会将所有卡片变为红色,而不仅仅是价格超过 £ 的卡片3,00

我不知道我做错了什么。任何帮助将不胜感激

这里还有从控制台测试代码的链接: :https://www.monoprix.fr/courses/legumes-frais-mpx_c0000400?page=3

这是我的sn-p:

function exercise_3() {
  var price = document.querySelectorAll(".grocery-item__normal-price");
  var block = document.querySelectorAll(".grocery-item-item");
  let changePriceColor = 300;

  block.forEach((card) => {
    price.forEach((p) => {
      var a = p.innerText.slice(0, 4).replace(/,/g, "");
      if (a > changePriceColor) {
        card.style.background = "red";
      } else {
        return "";
      }
    });
  });
}

exercise_3();
<div class="grocery-item-item">
  <div class="grocery-item__description-offre">
    <a href="/courses/artichaut-blanc--2414383-p">
      <div class="grocery-item__description-wrapper">
        <div class="grocery-item__dimmer"></div>
        <div class="grocery-item__product-card-content discount">
          <div class="grocery-item__product-img">
            <img 
              data-tc='["","tc_event_20",""]' 
              data-tcdata='{"tc_event_11":0,"tc_event_20":{"ecommerceGA":"product_click","productId":2414383,"quantity":0},"tc_event_39":{"action":"cross sell | undefined","position":0}}' 
              src="https://cdn.monoprix.fr/cdn-cgi/image/width=180,quality=60,format=auto,metadata=none/assets/images/grocery/2414383/580x580.jpg"
              width="100" 
              height="100" 
              centered="true"
            >
          </div>
          <div class="grocery-item__description">
            <div class="grocery-item-brand">
              <p></p>
            </div>
            <div class="grocery-item-range">ARTICHAUT BLANC</div>
            <div class="conditioning-description">L'unité</div>
          </div>
        </div>
      </div>
      <div class="withPromotionBand-sc-1jbwr08-0 cfLNRM grocery-item__promotions_band">
        <div class="promo_map">
          <div class="promo_band _red">
            <div class="promo_red">-50%</div>
            sur le 2ème
          </div>
          {" "}
        </div>
      </div>
    </a>
  </div>
  <div class="grocery-item__price-cart">
    <div class="grocery-item__price-wrapper">
      <div class="grocery-item__price-line-through"></div>
      <div class="grocery-item__normal-price">2,00 €</div>
      <div class="grocery-item__price-unit">
        <p>2,00 € / p</p>
      </div>
    </div>
    <div class="styledAddToCartButton-sc-15efgme-0 fNiyOV">
      <div 
        class="add-to-cart-button__add-button" 
        id="addToCartButton-2414383" 
        value="AddToCart" 
        data-tc='["tc_event_20",""]' 
        data-tcdata='{"tc_event_20":{"ecommerceGA":"product_add","productId":2414383,"quantity":0},"tc_event_38":{"position":0,"productId":2414383}}'
      >
        <img 
          src="/contents/images/cart_icon.svg" 
          width="40" 
          height="40" 
          alt="panier" 
          class="pannel"
        >
      </div>
    </div>
  </div>
</div>
</>
</>;

【问题讨论】:

  • 你必须发布 HTML
  • @JaromandaX 完成
  • 如果您将其设为代码 sn-p,只需单击“运行代码 sn-p”即可在此处重现(因此我们可以看到什么不起作用),这更容易理解我/我们
  • 问题在于你如何构建你的 for 循环,它们会针对每张卡片进行迭代,并检查每个价格条件。

标签: javascript for-loop dom foreach


【解决方案1】:

问题是,对于所有卡片,您总是查看所有价格。相反,您应该只查看当前卡片内的价格。这可以通过card.querySelectorAll 完成,其中card 是当前块。

function exercise_3() {
  const blocks = document.querySelectorAll(".grocery-item-item");
  const changePriceColor = 300;

  blocks.forEach((card) => {
    const prices = card.querySelectorAll(".grocery-item__normal-price");
    prices.forEach((p) => {
      const a = p.innerText.slice(0, 4).replace(/,/g, "");
      
      if (a > changePriceColor) {
        card.style.background = "red";
      } else {
        return "";
      }
    });
  });
}

exercise_3();
.grocery-item-item {
  border: 1px solid;
}
<div class="grocery-item-item">
     <div class="grocery-item__normal-price">2,00 €</div>
     <div class="grocery-item__normal-price">2,00 €</div>
</div>

<div class="grocery-item-item">
     <div class="grocery-item__normal-price">4,00 €</div>
</div>

<div class="grocery-item-item">
     <div class="grocery-item__normal-price">1,00 €</div>
</div>

【讨论】:

    【解决方案2】:

    您构建嵌套 for 循环的方式导致您循环遍历每张卡的所有价格。对于第一张牌的含义,您查看所有价格,不可避免地有一张高于 300,因此它变成红色,然后转到下一张牌,再次查看所有价格,找到高于 300 的一张并将该牌也变成红色,这样一直持续到每张卡片都变红为止

    function exercise_3() {
      var price = document.querySelectorAll(".grocery-item__normal-price");
      let changePriceColor = 300;
    
      // So you don't need to run a forloop over the "block", 
      // instead you could just find the closest '.grocery-item-item' 
      // to the price that meets your condition, and change its background
      price.forEach((p) => {
        var a = p.innerText.slice(0, 4).replace(/,/g, "");
        if (a > changePriceColor) {
          const card = p.closest('.grocery-item-item')
          card.style.background = "red";
        } else {
          return "";
        }
      });
    
    }
    
    exercise_3();
    

    【讨论】:

      【解决方案3】:

      注意:.forEach() 没有 return 任何东西

      您可以在一个 .forEach() 方法中运行流控制语句,因为典型的 DOM 树是简单的父/子层次结构(&lt;table&gt;s 是例外)。

      以下函数传递3个参数:

      1. limit Number 与每个值进行比较的实数浮点数或整数
      2. priceTag String 包含文本或具有价格属性(表单控件)的元素的 CSS 选择器
      3. itemCard String 包含 priceTag 的元素的 CSS 选择器

      tooExpensive()

      1. 将所有 priceTag 收集到 NodeList 中
        const prices = document.querySelectorAll(priceTag);
        
      2. 然后将 NodeList 转换为数组以通过.forEach() 运行它
        [...prices].forEach(node => {...
        
      3. 接下来,它确定要提取的字符串类型以及是否存在任何一种:
        // <div>textContent</div> <!--or--> <input value="value">
        
        let text = node.textContent || node.value;
        if (text.length > 0) {...
        
      4. 当有值时,所有逗号“,”都被点“.”替换,然后除数字和点之外的所有字符都被删除。
        let price = text.replaceAll(',', '.').split(/[^0-9.]/).join(''); 
        
      5. 接下来,它确定 priceTag 是否有一个 itemCard 作为祖先
        let parent = node.closest(itemCard);
        
      6. 最后,如果价格大于limititemCard strong>(或 parent)确实存在,通过添加 class @987654335 来更改 parent 样式@
        if (parseFloat(price) > limit && parent) {
          parent.classList.add('red');
        }
        

      const tooExpensive = (limit, priceTag, itemCard) => {
        const prices = document.querySelectorAll(priceTag);
        [...prices].forEach(node => {
          let text = node.textContent || node.value;
          if (text.length > 0) {
            let price = text.replaceAll(',', '.').split(/[^0-9.]/).join('');
            //console.log(price);
            let parent = node.closest(itemCard);
            if (parseFloat(price) > limit && parent) {
              parent.classList.add('red');
            }
          }
        });
      };
      
      tooExpensive(3, '.price', '.item');
      .item {
        width: min-content;
        padding: 5px 10px;
        margin: 5px 0;
        border: 1px black solid;
      }
      
      .red {
        background: red;
        color: white;
      }
      <fieldset class='item'>
      <input class='price' value='$5.00'>
      </fieldset>
      <div class='item'>
      <input class='price' value='2,00'>
      </div>
      <section class='item'>
      <output class='price'>0.6</output>
      </section>
      <article class='item'>
      <p class='price'>8,00</p>
      </article>
      <div class='item'>
      <p class='price'>£3,00</p>
      </div>
      <aside class='item'>
      <div>2999</div>
      </aside>
      <nav>
      <fieldset class='price'>99</fieldset>
      </nav>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-27
        • 2010-11-18
        • 2013-03-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多