You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用forEach遍历数组时始终获取最后一个元素值的问题解决

问题:点击批量生成的选项卡始终获取最后一个对象的价格

我正在开发选项卡(tabs)功能,通过forEach方法在DOM中批量生成选项卡块,每个块对应数组中包含价格的对象。但点击选项卡时,始终只能获取到数组最后一个对象的价格值,请问如何实现点击对应块时获取其正确的价格?

原始代码

JavaScript

let plansVal = [{
    id: 1,
    price: "2,90",
    follows: "50"
  },
  {
    id: 2,
    price: "3,90",
    follows: "150"
  },
  {
    id: 3,
    price: "5,90",
    follows: "250"
  },
  {
    id: 4,
    price: "150,90",
    follows: "350"
  },
  {
    id: 5,
    preco: "300,90",
    follows: "450"
  },
  {
    id: 6,
    preco: "9,90",
    follows: "1000"
  },
  {
    id: 7,
    price: "19,90",
    follows: "1500"
  },
  {
    id: 8,
    price: ",30",
    follows: "2000"
  },
  {
    id: 9,
    price: "59,90",
    follows: "3000"
  },
  {
    id: 10,
    price: "99,90",
    follows: "3500"
  },
];

const tabs = add => {

  const plansContent = $(".plans-content");

  plansContent.append(`

            <div id="plan${add.id}" class="plan bg-dgrade-r-s">
                <div class="plan-text">
                    <span><strong>${add.follows}</strong></span>
                    <p>Seguidores</p>
                </div>
            </div>
        `);

  plansContent.click(function() {
    console.log(add.price);
  });
}

plansVal.forEach(add => tabs(add));

CSS

.plans {
  max-width: max-content;
  padding: 0;
}

.plans .plans-title {
  text-align: center;
  font-size: 1.3rem;
  margin-bottom: 25px;
}

.plans .plans-title b {
  color: var(--roxo);
}

.vector_donthavelikes {
  width: 90%;
}

.vector_donthavelikes img {
  max-width: 100%;
  display: block;
  margin: auto;
  image-rendering: optimizeSpeed;
}

.plans .plans-content {
  display: flex;
  justify-content: center;
  flex-flow: row wrap;
  place-items: center;
}

.plans .plans-content .plan {
  min-width: 125px;
  max-width: 125px;
  margin: 5px 3px;
  cursor: pointer;
}

.plans .plans-content .plan .plan-text {
  background-color: #fff;
  height: 80px;
  padding: 10px 5px;
  line-height: 20px;
}

.plans .plans-content .plan.active .plan-text {
  background-color: transparent;
}

.plans .plans-content .plan.active .plan-text p {
  color: #fff;
}

.plans .plans-content .plan .plan-text span {
  font-size: 1.2rem;
  margin-top: 10px;
  display: block;
}

.plans .plans-content .plan .plan-text p {
  font-size: 0.9rem;
  color: var(--cinza-escuro);
}

.plans .plans-content .plan.active {
  color: #fff;
}

.plans .plans-content .plan,
.plans .plans-content .plan.active {
  padding: 7px;
  border-radius: 5px;
  text-align: center;
}

.plans .plans-content .plan.active {
  background-image: -moz-linear-gradient( -151deg, rgb(143, 23, 219) 0%, rgb(220, 134, 125) 100%);
  background-image: -webkit-linear-gradient( -151deg, rgb(143, 23, 219) 0%, rgb(220, 134, 125) 100%);
  background-image: -ms-linear-gradient( -151deg, rgb(143, 23, 219) 0%, rgb(220, 134, 125) 100%);
}

.plans div .plan-value {
  font-size: 1.7rem;
  font-weight: 550;
}

.plans div .plan-value sup {
  color: var(--cinza);
}

HTML

<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<div class="plans mx-auto col-sm-5">
  <div class="d-flex align-items-center p-3">
    <h3 class="plans-title">
      É hora de dar engajamento ao seu Instagram com Seguidores Reais.
      <b>Entrega em poucos minutos.</b>
    </h3>

    <div class="vector_donthavelikes">
      <img src="/src/imgs/others/donthavelikes.png" alt="">
    </div>
  </div>

  <div class="plans-content"></div>

  <div class="d-flex mt-4 flex-column col-sm-4 col-md-5 mx-auto text-center">
    <p id="planValue" class="plan-value"><sup>R$</sup> 3.99</p>
    <a href="#" class="btn-comn mx-auto">
                            Buy
                        </a>
  </div>
</div>

问题原因

  1. 重复绑定事件到父元素:每次循环都给plansContent绑定一次click事件,最终父元素上叠加了10个点击事件,且由于闭包特性,所有事件中的add变量最终都会指向数组的最后一个元素。
  2. 未区分点击目标:事件绑定在父元素上,但没有判断点击的是哪个子选项卡,无法关联到对应的对象数据。

解决方案

方案1:给每个选项卡单独绑定事件

生成每个选项卡后,直接给该元素绑定点击事件,确保每个事件捕获当前循环的add对象:

const tabs = add => {
  const plansContent = $(".plans-content");
  // 创建单个选项卡jQuery对象
  const $plan = $(`
    <div id="plan${add.id}" class="plan bg-dgrade-r-s">
        <div class="plan-text">
            <span><strong>${add.follows}</strong></span>
            <p>Seguidores</p>
        </div>
    </div>
  `);
  
  // 绑定点击事件,兼容price/preco字段
  $plan.click(function() {
    const price = add.price || add.preco;
    console.log(price);
    // 更新页面价格显示
    $("#planValue").html(`<sup>R$</sup> ${price}`);
  });
  
  plansContent.append($plan);
}

plansVal.forEach(add => tabs(add));

方案2:事件委托+自定义data属性(推荐)

只给父元素绑定一次点击事件,通过data-*属性存储价格,点击时从目标元素获取数据,性能更优:

// 先统一处理数组中的价格字段,避免后续判断
plansVal.forEach(item => {
  item.price = item.price || item.preco;
});

const tabs = add => {
  const plansContent = $(".plans-content");
  plansContent.append(`
    <div id="plan${add.id}" class="plan bg-dgrade-r-s" data-price="${add.price}">
        <div class="plan-text">
            <span><strong>${add.follows}</strong></span>
            <p>Seguidores</p>
        </div>
    </div>
  `);
}

plansVal.forEach(add => tabs(add));

// 父元素绑定一次事件,通过事件委托处理子元素点击
$(".plans-content").click(function(e) {
  // 找到点击的.plan元素
  const $targetPlan = $(e.target).closest(".plan");
  if ($targetPlan.length) {
    const price = $targetPlan.data("price");
    console.log(price);
    $("#planValue").html(`<sup>R$</sup> ${price}`);
  }
});

方案3:闭包捕获循环变量(不推荐)

通过立即执行函数固定每次循环的add变量,但会导致父元素绑定多个事件,性能较差:

const tabs = add => {
  const plansContent = $(".plans-content");
  plansContent.append(`
    <div id="plan${add.id}" class="plan bg-dgrade-r-s">
        <div class="plan-text">
            <span><strong>${add.follows}</strong></span>
            <p>Seguidores</p>
        </div>
    </div>
  `);
  
  // 用立即执行函数捕获当前add
  (function(currentAdd) {
    plansContent.click(function(e) {
      const $target = $(e.target).closest(`#plan${currentAdd.id}`);
      if ($target.length) {
        const price = currentAdd.price || currentAdd.preco;
        console.log(price);
        $("#planValue").html(`<sup>R$</sup> ${price}`);
      }
    });
  })(add);
}

plansVal.forEach(add => tabs(add));

说明:方案2是最优选择,既避免重复绑定事件,又能清晰地关联元素与数据,同时解决了数组中价格字段不一致的问题。

内容的提问来源于stack exchange,提问作者Carlos Eduardo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 16:27:24