如何实现购物车无刷新删除与商品数量更新功能?
实现购物车无刷新更新与删除功能
核心改动思路
用AJAX异步请求后端接口更新会话中的购物车数据,同时前端直接修改DOM元素展示最新状态,彻底避免页面刷新。
第一步:引入jQuery
在<head>标签内添加jQuery库(若项目已引入可跳过):
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
第二步:修改PHP逻辑(支持AJAX请求)
在原PHP代码开头添加AJAX请求处理分支,完成操作后返回JSON数据而非整个页面:
<?php session_start(); // 初始化AJAX响应数据 $response = ['success' => false]; // 删除商品逻辑 if(isset($_GET['delete_id'])) { $delete_id = (int)$_GET['delete_id']; foreach($_SESSION['cart'] as $key => $product) { if($product['id'] === $delete_id) { unset($_SESSION['cart'][$key]); $response['success'] = true; $response['cart_count'] = count($_SESSION['cart']); } } // 识别AJAX请求,直接返回JSON if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { header('Content-Type: application/json'); echo json_encode($response); exit; } } // 更新数量逻辑 if(isset($_GET['update_id']) && isset($_GET['quantity'])) { $update_id = (int)$_GET['update_id']; $quantity = (int)$_GET['quantity']; foreach($_SESSION['cart'] as $key => $product) { if($product['id'] === $update_id) { $_SESSION['cart'][$key]['quantity'] = $quantity; $response['success'] = true; $response['cart_count'] = count($_SESSION['cart']); $response['price'] = $product['price']; // 返回单价供前端计算 } } // 识别AJAX请求,直接返回JSON if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { header('Content-Type: application/json'); echo json_encode($response); exit; } } ?>
第三步:修正HTML结构(补全必要类名)
在生成商品小计的<span>标签中添加product-subtotal类,让总价计算函数能正确获取数据:
// 替换原代码中的小计生成行 echo '<p>Subtotal: $<span id="product-'.$product['id'].'-subtotal" class="product-subtotal">'.number_format($subtotal,2).'</span></p>';
第四步:重写JavaScript函数(替换刷新为AJAX)
替换原有的<script>代码,用AJAX异步请求更新数据:
<script> function incrementQuantity(id) { var currentQuantity = parseInt(document.getElementById('product-' + id + '-quantity').innerHTML); var newQuantity = currentQuantity + 1; updateQuantity(id, newQuantity); } function decrementQuantity(id) { var currentQuantity = parseInt(document.getElementById('product-' + id + '-quantity').innerHTML); if(currentQuantity > 1) { var newQuantity = currentQuantity - 1; updateQuantity(id, newQuantity); } } function updateQuantity(id, value) { $.ajax({ url: 'cart.php', type: 'GET', data: { update_id: id, quantity: value }, dataType: 'json', success: function(res) { if(res.success) { // 更新页面显示的数量 document.getElementById('product-' + id + '-quantity').innerHTML = value; // 计算并更新小计 var subtotal = (res.price * value).toFixed(2); document.getElementById('product-' + id + '-subtotal').innerHTML = subtotal; // 更新总价 updateTotal(); // 更新购物车菜单的数量 document.querySelector('#cart-menu a').innerHTML = 'Cart (' + res.cart_count + ')'; } } }); } function removeFromCart(id) { $.ajax({ url: 'cart.php', type: 'GET', data: { delete_id: id }, dataType: 'json', success: function(res) { if(res.success) { // 移除页面上的商品区块及分隔线 var quantityElement = document.getElementById('product-' + id + '-quantity'); var productBlock = quantityElement.parentElement; while(productBlock && productBlock.id !== 'cart-list') { if(productBlock.nextElementSibling?.tagName === 'HR') { productBlock.nextElementSibling.remove(); } var parent = productBlock.parentElement; productBlock.remove(); productBlock = parent; } // 更新总价 updateTotal(); // 更新购物车菜单的数量 document.querySelector('#cart-menu a').innerHTML = 'Cart (' + res.cart_count + ')'; // 购物车为空时显示提示 if(res.cart_count === 0) { document.getElementById('cart-list').innerHTML = '<p>Your cart is empty</p>'; } } } }); } function updateTotal() { var total = 0; var subtotals = document.getElementsByClassName('product-subtotal'); for (var i = 0; i < subtotals.length; i++) { total += parseFloat(subtotals[i].innerHTML); } document.getElementById('total').innerHTML = total.toFixed(2); } </script>
关键说明
- AJAX请求识别:通过
HTTP_X_REQUESTED_WITH请求头判断是否为AJAX请求,仅返回必要的JSON数据,避免输出完整页面。 - 前端状态同步:请求成功后直接修改DOM元素,实时更新数量、小计、总价和购物车计数,全程无刷新。
- 边界场景处理:删除最后一件商品时自动切换为空购物车提示,保证页面逻辑完整。
内容的提问来源于stack exchange,提问作者Paul Hagi
相关产品推荐
相关产品推荐

