如何用Ajax将WooCommerce优惠券模块移至购物车总价上方并修复刷新问题
修复WooCommerce移至cart-totals.php后的优惠券Ajax失效问题
将优惠券模块从cart.php迁移到cart-totals.php后,通过钩子成功显示了优惠券输入字段,优惠券可正常应用,但页面会强制刷新,原有的Ajax无刷新功能失效。现有实现代码如下:
add_action( 'woocommerce_before_cart_totals', 'custom_display_coupon_form_below_proceed_checkout', 25 ); function custom_display_coupon_form_below_proceed_checkout() { ?> <form class="woocommerce-coupon-form" action="<?php echo esc_url( wc_get_cart_url() ); ?>" method="post"> <?php if ( wc_coupons_enabled() ) { ?> <div class="coupon under-proceed"> <input type="text" name="coupon_code" class="input-text" id="coupon_code" value="" placeholder="<?php esc_attr_e( 'Coupon code', 'woocommerce' ); ?>" style="width: 100%" /> <button type="submit" class="button" name="apply_coupon" value="<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>" style="width: 100%"><?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?></button> </div> <?php } ?> </form> <?php }
问题原因
WooCommerce默认的优惠券Ajax交互逻辑,是绑定在购物车页面原始优惠券表单的DOM元素上,自定义手动编写的表单没有被自动绑定Ajax事件监听,导致点击提交时触发了表单默认的页面刷新行为。
修复方案
方案1:使用WooCommerce内置模板输出表单(推荐)
直接调用WooCommerce自带的优惠券模板,该模板已包含完整的Ajax事件绑定逻辑,无需额外编写JS:
add_action( 'woocommerce_before_cart_totals', 'custom_display_coupon_form_below_proceed_checkout', 25 ); function custom_display_coupon_form_below_proceed_checkout() { if ( wc_coupons_enabled() ) { // 加载默认优惠券模板,自动带Ajax功能 wc_get_template( 'cart/coupon.php' ); } }
如果需要自定义样式,可复制wp-content/plugins/woocommerce/templates/cart/coupon.php到你的主题目录woocommerce/cart/coupon.php,再修改HTML结构和样式,这样既保留Ajax功能,又能自定义布局。
方案2:手动添加Ajax事件监听
如果坚持自定义表单HTML,需要添加JS代码拦截表单提交,触发WooCommerce的Ajax请求:
首先修改PHP函数,给表单添加唯一类名方便选择:
add_action( 'woocommerce_before_cart_totals', 'custom_display_coupon_form_below_proceed_checkout', 25 ); function custom_display_coupon_form_below_proceed_checkout() { ?> <form class="woocommerce-coupon-form custom-cart-coupon-form" action="<?php echo esc_url( wc_get_cart_url() ); ?>" method="post"> <?php if ( wc_coupons_enabled() ) { ?> <div class="coupon under-proceed"> <input type="text" name="coupon_code" class="input-text" id="custom_coupon_code" value="" placeholder="<?php esc_attr_e( 'Coupon code', 'woocommerce' ); ?>" style="width: 100%" /> <button type="submit" class="button" name="apply_coupon" value="<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>" style="width: 100%"><?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?></button> </div> <?php } ?> </form> <?php }
然后添加JS代码(可放在主题的functions.php或自定义JS文件中):
add_action( 'wp_footer', 'custom_coupon_ajax_script' ); function custom_coupon_ajax_script() { if ( is_cart() && wc_coupons_enabled() ) { ?> <script> (function($) { // 拦截自定义优惠券表单的提交事件 $('.custom-cart-coupon-form').on('submit', function(e) { e.preventDefault(); var $form = $(this); var couponCode = $form.find('input[name="coupon_code"]').val(); // 触发WooCommerce的优惠券Ajax请求 $.ajax({ type: 'POST', url: wc_cart_params.ajax_url, data: { action: 'apply_coupon', coupon_code: couponCode }, beforeSend: function() { $form.find('button').prop('disabled', true).text('<?php esc_attr_e( 'Applying...', 'woocommerce' ); ?>'); }, success: function(response) { // 重新加载购物车片段,更新总价 $(document.body).trigger('wc_update_cart'); // 清空优惠券输入框 $form.find('input[name="coupon_code"]').val(''); // 恢复按钮状态 $form.find('button').prop('disabled', false).text('<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>'); }, error: function() { $form.find('button').prop('disabled', false).text('<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>'); } }); }); })(jQuery); </script> <?php } }
额外说明
- 方案1更简洁,能自动同步WooCommerce的更新,避免后续版本兼容问题;
- 方案2适合需要高度自定义表单结构的场景,需确保JS代码与WooCommerce的Ajax参数兼容。
内容的提问来源于stack exchange,提问作者Chandra Sekhar Rao Bali
相关产品推荐
相关产品推荐

