如何在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里写了新的点击事件处理逻辑,这个逻辑里:
- 没有获取
productId就直接调用saveVoteToServer,导致后续逻辑拿不到productId - 之前定义的
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
相关产品推荐
相关产品推荐

