WooCommerce AJAX搜索加购:首次点击按钮页面刷新问题求助
问题
这是一款支持分类筛选的WooCommerce产品AJAX实时搜索功能,当前存在异常:首次点击“加入购物车”按钮时,页面会刷新且不显示“查看购物车”选项;第二次点击则可正常显示“查看购物车”且无页面刷新。需要修复仅首次点击出现的页面加载问题。
现有代码
PHP代码
function perform_product_search() { $searchQuery = isset($_POST['search_query']) ? sanitize_text_field($_POST['search_query']) : ''; $categoryFilter = isset($_POST['category_filter']) ? $_POST['category_filter'] : array(); $args = array( 'post_type' => 'product', 'post_status' => 'publish', 'posts_per_page' => -1, // 显示所有产品 's' => $searchQuery, ); if (!empty($categoryFilter)) { $args['tax_query'] = array( array( 'taxonomy' => 'product_cat', 'field' => 'term_id', 'terms' => $categoryFilter, 'operator' => 'IN', ), ); } $loop = new WP_Query($args); $count = 0; ob_start(); // 启动输出缓冲 if ($loop->have_posts()) { echo '<div class="product-row">'; // 开始产品行 while ($loop->have_posts()) : $loop->the_post(); if ($count % 4 === 0 && $count > 0) { echo '</div><div class="product-row">'; // 每4个产品后换行 } echo '<div class="col-md-3">'; // 添加列容器 wc_get_template_part('content', 'product'); echo '</div>'; // 关闭列容器 $count++; endwhile; echo '</div>'; // 关闭最后一行 } else { echo __('未找到产品'); } wp_reset_postdata(); $output = ob_get_clean(); // 获取缓冲内容 // 无搜索条件时显示所有产品 if (empty($searchQuery) && empty($categoryFilter)) { $args_all = array( 'post_type' => 'product', 'post_status' => 'publish', 'posts_per_page' => -1, ); $loop_all = new WP_Query($args_all); $count_all = 0; ob_start(); if ($loop_all->have_posts()) { echo '<div class="product-row">'; while ($loop_all->have_posts()) : $loop_all->the_post(); if ($count_all % 4 === 0 && $count_all > 0) { echo '</div><div class="product-row">'; } echo '<div class="col-md-3">'; wc_get_template_part('content', 'product'); echo '</div>'; $count_all++; endwhile; echo '</div>'; } else { echo __('未找到产品'); } wp_reset_postdata(); $output_all = ob_get_clean(); if (empty($output)) { $output = $output_all; } } echo $output; die(); } add_action('wp_ajax_perform_product_search', 'perform_product_search'); add_action('wp_ajax_nopriv_perform_product_search', 'perform_product_search'); // AJAX加入购物车 function add_to_cart() { $product_id = isset($_POST['product_id']) ? absint($_POST['product_id']) : 0; $quantity = isset($_POST['quantity']) ? absint($_POST['quantity']) : 1; if ($product_id > 0) { WC()->cart->add_to_cart($product_id, $quantity); // 返回更新后的购物车片段 ob_start(); woocommerce_mini_cart(); $mini_cart = ob_get_clean(); wp_send_json_success(array( 'fragments' => apply_filters('woocommerce_add_to_cart_fragments', array( '.widget_shopping_cart_content' => $mini_cart, )), 'cart_url' => wc_get_cart_url() // 新增购物车URL返回字段 )); } wp_send_json_error(); } add_action('wp_ajax_add_to_cart', 'add_to_cart'); add_action('wp_ajax_nopriv_add_to_cart', 'add_to_cart'); // 短代码实现 function realtime_product_search_shortcode() { ob_start(); // 获取产品分类 $categories = get_terms(array( 'taxonomy' => 'product_cat', 'hide_empty' => true, ));?> <div class="realtime-product-search"> <input type="text" id="product-search" placeholder="搜索产品..." /> <div id="category-filter"> <h4>按分类筛选:</h4> <label> <input type="checkbox" name="category_filter[]" value="" /> 所有分类 </label> <?php foreach ($categories as $category) : ?> <label> <input type="checkbox" name="category_filter[]" value="<?php echo $category->term_id; ?>" /> <?php echo $category->name; ?> </label> <?php endforeach; ?> </div> <div id="search-results"></div> </div> <?php return ob_get_clean(); } add_shortcode('realtime_product_search', 'realtime_product_search_shortcode');
JS代码
(function($){ $(document).ready(function ($) { var typingTimer; var doneTypingInterval = 500; // 输入延迟时间(毫秒) function performProductSearch() { clearTimeout(typingTimer); typingTimer = setTimeout(function() { var searchQuery = $('#product-search').val(); var categoryFilter = []; $('input[name="category_filter[]"]:checked').each(function() { var value = $(this).val(); if (value !== '') { categoryFilter.push(value); } }); $.ajax({ url: realtime_product_search_ajax.ajax_url, type: 'POST', data: { action: 'perform_product_search', search_query: searchQuery, category_filter: categoryFilter }, beforeSend: function() { $('#search-results').html('搜索中...'); }, success: function(response) { $('#search-results').html(response); } }); }, doneTypingInterval); } // 输入变化时触发搜索 $('#product-search, input[name="category_filter[]"]').on('change keyup', function() { performProductSearch(); }); // 加入购物车功能 $(document).on('submit', '.add-to-cart-form', function(e) { e.preventDefault(); // 优先阻止表单默认提交行为 var form = $(this); var product_id = form.find('.product-id').val(); var quantity = form.find('.quantity').val(); // 移除已存在的查看购物车按钮,避免重复添加 form.next('.button.wc-forward').remove(); $.ajax({ url: realtime_product_search_ajax.ajax_url, type: 'POST', data: { action: 'add_to_cart', product_id: product_id, quantity: quantity }, beforeSend: function() { // 可添加加载动画 }, success: function(response) { if (response.success) { // 更新购物车片段 $(document.body).trigger('wc_fragment_refresh'); // 提示添加成功 alert('产品已加入购物车'); // 显示查看购物车按钮 var viewCartUrl = response.data.cart_url; var viewCartButton = '<a href="' + viewCartUrl + '" class="button wc-forward">查看购物车</a>'; form.after(viewCartButton); } }, error: function() { alert('加入购物车失败,请重试'); } }); }); }); })(jQuery);
修复方案
1. 核心问题分析
首次点击刷新的原因有两个:
- PHP端未返回购物车URL,JS尝试获取不存在的
response.fragments.cart_url导致代码报错,无法完全阻止表单默认提交; - 未处理重复添加按钮的逻辑,首次AJAX成功后按钮未正确生成。
2. 具体修复步骤
步骤1:PHP端补充购物车URL返回
在add_to_cart函数的成功响应中添加cart_url字段,使用WooCommerce内置函数wc_get_cart_url()获取购物车地址:
wp_send_json_success(array( 'fragments' => apply_filters('woocommerce_add_to_cart_fragments', array( '.widget_shopping_cart_content' => $mini_cart, )), 'cart_url' => wc_get_cart_url() // 新增此行 ));
步骤2:JS端修正逻辑
- 确保
e.preventDefault()在函数最开始执行,彻底阻止表单默认提交; - 修正购物车URL的获取路径为
response.data.cart_url; - 添加移除已有按钮的逻辑,避免重复生成;
- 增加AJAX错误处理,提升用户体验。
步骤3:检查产品表单字段
确认AJAX加载的产品表单中包含.product-id隐藏字段,若缺失需在WooCommerce产品模板中添加:
<input type="hidden" class="product-id" value="<?php echo get_the_ID(); ?>" />
内容的提问来源于stack exchange,提问作者SavPhill
相关产品推荐
相关产品推荐

