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

如何在JavaScript中正确获取PHP传入的productId值?

问题:productId始终为undefined,无法获取正确值

我无法找到问题所在,productId始终为undefined,尝试多种方法后仍未解决,预期值应为10。

PHP代码

$products_id = 10;

while ($Qreviews->fetch()) {
  $reviews_id = $Qreviews->valueInt('reviews_id');
  $products_reviews_content .= '
<div class="moduleProductsInfoReviewCustomersNotice">
  this comment is use full ?
  <strong><span class="toggleButton yesButton" id="' . $uniqueId . '_yesButton" data-unique-id="' . $uniqueId . '" data-product-id="' . $products_id . '">Oui</span></strong>
  <span class="toggleValue yesValue">(0)</span>
  <strong><span class="toggleButton noButton" id="' . $uniqueId . '_noButton" data-unique-id="' . $uniqueId . '" data-product-id="' . $products_id . '">Non</span></strong>
  <span class="toggleValue noValue">(0)</span>
  <span class="thankYouMessage" style="display: none;">Merci</span>
</div>
';

  $products_reviews_content .= '<script defer src="voted_review.js"></script>' . "
";
}

JavaScript代码

问题出在这行代码,无法获取到正确数据,值始终为undefined:

const productId = this.getAttribute('data-product-id');

完整JavaScript代码:

document.addEventListener("DOMContentLoaded", function () {
  // 检查用户是否已投票
  function hasUserVoted(reviewId) {
    const votedReviews = getVotedReviews();
    return votedReviews.includes(reviewId);
  }

  // 获取本地存储的已投票评论ID
  function getVotedReviews() {
    const votedReviews = localStorage.getItem('votedReviews');
    return votedReviews ? JSON.parse(votedReviews) : [];
  }

  // 标记评论为已投票并存储
  function markReviewAsVoted(reviewId) {
    const votedReviews = getVotedReviews();
    if (!votedReviews.includes(reviewId)) {
      votedReviews.push(reviewId);
      localStorage.setItem('votedReviews', JSON.stringify(votedReviews));
    }
  }

  // 处理"Oui"按钮点击
  function handleButtonClickYes() {
    const reviewId = this.getAttribute('data-unique-id');
    const productId = this.getAttribute('data-product-id');

    if (productId) {
      if (!hasUserVoted(reviewId)) {
        const parentDiv = this.closest(".moduleProductsInfoReviewCustomersNotice");
        const noButton = parentDiv.querySelector(".noButton");
        const yesValue = parentDiv.querySelector(".yesValue");
        const noValue = parentDiv.querySelector(".noValue");
        const thankYouMessage = parentDiv.querySelector(".thankYouMessage");

        noButton.style.display = "none";
        noValue.style.display = "none";
        yesValue.style.display = "none";
        thankYouMessage.style.display = "inline";

        markReviewAsVoted(reviewId);

        // 发送AJAX请求保存投票到服务器
        saveVoteToServer(reviewId, 1, productId);
      }
    } else {
      console.error("Product ID element not found.");
    }
  }

// 处理"Non"按钮点击
  function handleButtonClickNo() {
    const reviewId = this.getAttribute('data-unique-id');
    const productId = this.getAttribute('data-product-id');

    if (productId) {
      if (!hasUserVoted(reviewId)) {
        const parentDiv = this.closest(".moduleProductsInfoReviewCustomersNotice");
        const yesButton = parentDiv.querySelector(".yesButton");
        const yesValue = parentDiv.querySelector(".yesValue");
        const noValue = parentDiv.querySelector(".noValue");
        const thankYouMessage = parentDiv.querySelector(".thankYouMessage");

        yesButton.style.display = "none";
        yesValue.style.display = "none";
        noValue.style.display = "none";
        thankYouMessage.style.display = "inline";

        markReviewAsVoted(reviewId);

        // 发送AJAX请求保存投票到服务器
        saveVoteToServer(reviewId, 0, productId);
      }
    } else {
      console.error("Product ID element not found.");
    }
  }


  // 发送AJAX请求保存投票到服务器
  function saveVoteToServer(reviewId, vote, productId) {
    const xhr = new XMLHttpRequest();
    xhr.open("POST", 'voted_review.php', true);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
            // 处理服务器响应(如有需要)
            console.log('Vote saved for review ' + reviewId + ': ' + vote + "&product_id=" + productId);
        }
    };
    xhr.send("reviewId=" + reviewId + "&vote=" + vote + "&product_id=" + productId);

  }

  // 选择所有带有data-unique-id属性的元素
  const reviewButtons = document.querySelectorAll('[data-unique-id]');

  // 为每个按钮添加事件监听器
  reviewButtons.forEach(function (button) {
    button.addEventListener("click", function () {
      const reviewId = this.getAttribute('data-unique-id');
      if (!hasUserVoted(reviewId)) {
        const parentDiv = this.closest(".moduleProductsInfoReviewCustomersNotice");
        const yesButton = parentDiv.querySelector(".yesButton");
        const noButton = parentDiv.querySelector(".noButton");
        const yesValue = parentDiv.querySelector(".yesValue");
        const noValue = parentDiv.querySelector(".noValue");
        const thankYouMessage = parentDiv.querySelector(".thankYouMessage");

        if (this === yesButton) {
          noButton.style.display = "none";
          noValue.style.display = "none";
        } else {
          yesButton.style.display = "none";
          yesValue.style.display = "none";
        }

        thankYouMessage.style.display = "inline";

        markReviewAsVoted(reviewId);

        // 发送AJAX请求保存投票到服务器
        saveVoteToServer(reviewId, this === yesButton ? 1 : 0);
      }
    });
  });
});

问题原因及解决方案

问题根源

你定义了handleButtonClickYes和handleButtonClickNo两个处理函数,但实际并没有给按钮绑定这两个函数。反而在reviewButtons.forEach里写了新的点击事件处理逻辑,这个逻辑里:

  1. 没有获取productId就直接调用saveVoteToServer,导致后续逻辑拿不到productId
  2. 之前定义的handleButtonClickYes/No完全没被使用,里面的productId获取逻辑根本没执行

修复方案

两种选择二选一即可:

方案一:使用已定义的handleButtonClickYes/No函数

修改按钮事件绑定部分,直接给对应按钮绑定处理函数,同时删除原来的reviewButtons.forEach代码:

// 选择yes和no按钮分别绑定处理函数
document.querySelectorAll('.yesButton').forEach(btn => btn.addEventListener('click', handleButtonClickYes));
document.querySelectorAll('.noButton').forEach(btn => btn.addEventListener('click', handleButtonClickNo));

方案二:修复现有点击事件处理逻辑

保留现有绑定逻辑,在处理函数里获取productId并传给saveVoteToServer:

// 为每个按钮添加事件监听器
reviewButtons.forEach(function (button) {
  button.addEventListener("click", function () {
    const reviewId = this.getAttribute('data-unique-id');
    const productId = this.getAttribute('data-product-id'); // 新增获取productId
    if (!hasUserVoted(reviewId)) {
      const parentDiv = this.closest(".moduleProductsInfoReviewCustomersNotice");
      const yesButton = parentDiv.querySelector(".yesButton");
      const noButton = parentDiv.querySelector(".noButton");
      const yesValue = parentDiv.querySelector(".yesValue");
      const noValue = parentDiv.querySelector(".noValue");
      const thankYouMessage = parentDiv.querySelector(".thankYouMessage");

      if (this === yesButton) {
        noButton.style.display = "none";
        noValue.style.display = "none";
      } else {
        yesButton.style.display = "none";
        yesValue.style.display = "none";
      }

      thankYouMessage.style.display = "inline";

      markReviewAsVoted(reviewId);

      // 发送AJAX请求保存投票到服务器,传入productId
      saveVoteToServer(reviewId, this === yesButton ? 1 : 0, productId);
    }
  });
});

额外建议

  • 可以使用dataset属性简化data-*属性获取:this.dataset.productId代替this.getAttribute('data-product-id')
  • PHP循环里重复添加<script>标签没必要,把<script defer src="voted_review.js"></script>放在页面底部即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:15:53