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

WooCommerce选择特定订单类型后配送方式隐藏后复现问题求助

解决WooCommerce结账页配送方式隐藏后重新显示的问题

问题说明

在WooCommerce结账页添加了自定义「订单类型」选择字段,需求是:

  • 选择「到店用餐」或「到店自提」时,仅保留免费配送(ID:7)选项,隐藏其他配送方式
  • 选择「配送上门」时,仅保留平邮(ID:6)选项,隐藏其他配送方式

但当前功能仅生效约1秒,结账页面加载/更新完成后,被隐藏的配送选项会重新显示。使用主题为Astra,相关代码如下:

// Add the custom field for "Order Type"
add_action('woocommerce_checkout_billing', 'before_billing_fields', 5);

function before_billing_fields() {
    $checkout = WC()->checkout;

    echo '<h3>' . __('Order Type', 'sdm') . '</h3>';

    woocommerce_form_field('delivery_method', array(
        'type' => 'select',
        'options' => array(
            'delivery' => __('Delivery', 'sdm'),
            'dine_in' => __('Dine In', 'sdm'),
            'pick_up' => __('Pick Up', 'sdm'),
        ),
        'class' => array('delivery_method form-row-wide'),
        'clear' => true,
    ), $checkout->get_value('delivery_method'));
}

// The jQuery script
add_action( 'wp_footer', 'custom_checkout_script' );
function custom_checkout_script() {
    // Only on the checkout page
    if( ! is_checkout() && ! is_wc_endpoint_url( 'order-received' ) )
        return;
    ?>
    <script type="text/javascript">
        jQuery( function($){
            var a = 'select#delivery_method',
                b = 'input[name^="shipping_method[0]"]',
                d = 'flat_rate:6', // Flat Rate ID
                e = 'free_shipping:7'; // Free Shipping ID

            // Function to set shipping method to Free Shipping
            function setFreeShipping() {
                $(b + '[value="' + e + '"]').prop("checked", true);
                $( document.body ).trigger( 'update_checkout' );
            }

            // Function to set shipping method to Flat Rate
            function setFlatRate() {
                $(b + '[value="' + d + '"]').prop("checked", true);
                $( document.body ).trigger( 'update_checkout' );
            }

            // Function to hide unselected shipping methods
            function hideUnselectedShipping() {
                var selectedMethod = $(b + ':checked').val();
                $(b).each(function() {
                    var id = $(this).val();
                    if (id != selectedMethod) {
                        $(this).closest('li').hide();
                    } else {
                        $(this).closest('li').show();
                    }
                });
            }

            // Set the default delivery method to "Delivery" and trigger change event
            $(a).val('delivery').change();
            hideUnselectedShipping();

            // Live action event: On Select "delivery_method" change
            $(a).change( function () {
                if ($(this).val() == 'pick_up' || $(this).val() == 'dine_in') {
                    setFreeShipping(); // Change to Free Shipping for Dine In or Pick Up
                } else {
                    setFlatRate(); // Change to Flat Rate for Delivery
                }
                hideUnselectedShipping();
            });

            // Live action event: On Shipping method change
            $( 'form.checkout' ).on( 'change', b, function() {
                // If Free shipping is not selected, we change "delivery_method" select field to "post"
                if ($(this).val() != e) {
                    $(a).val('delivery');
                    setFlatRate(); // Change to Flat Rate when another method is selected
                }
                hideUnselectedShipping();
            });
        });
    </script>
    <?php
}

问题原因

调用update_checkout后,WooCommerce会重新渲染配送方式区域,之前通过JS隐藏的元素会被重置显示,导致隐藏效果失效。

解决方案

添加对updated_checkout事件的监听,在结账页面更新完成后重新执行隐藏逻辑;同时调整默认值设置逻辑,避免重复触发不必要的更新。

修改后的完整代码:

// Add the custom field for "Order Type"
add_action('woocommerce_checkout_billing', 'before_billing_fields', 5);

function before_billing_fields() {
    $checkout = WC()->checkout;

    echo '<h3>' . __('Order Type', 'sdm') . '</h3>';

    woocommerce_form_field('delivery_method', array(
        'type' => 'select',
        'options' => array(
            'delivery' => __('Delivery', 'sdm'),
            'dine_in' => __('Dine In', 'sdm'),
            'pick_up' => __('Pick Up', 'sdm'),
        ),
        'class' => array('delivery_method form-row-wide'),
        'clear' => true,
    ), $checkout->get_value('delivery_method'));
}

// The jQuery script
add_action( 'wp_footer', 'custom_checkout_script' );
function custom_checkout_script() {
    // Only on the checkout page
    if( ! is_checkout() && ! is_wc_endpoint_url( 'order-received' ) )
        return;
    ?>
    <script type="text/javascript">
        jQuery( function($){
            var deliverySelect = 'select#delivery_method',
                shippingInputs = 'input[name^="shipping_method[0]"]',
                flatRateVal = 'flat_rate:6', // Flat Rate ID
                freeShippingVal = 'free_shipping:7'; // Free Shipping ID

            // Function to set shipping method to Free Shipping
            function setFreeShipping() {
                $(shippingInputs + '[value="' + freeShippingVal + '"]').prop("checked", true);
                $( document.body ).trigger( 'update_checkout' );
            }

            // Function to set shipping method to Flat Rate
            function setFlatRate() {
                $(shippingInputs + '[value="' + flatRateVal + '"]').prop("checked", true);
                $( document.body ).trigger( 'update_checkout' );
            }

            // Function to hide unselected shipping methods
            function hideUnselectedShipping() {
                var selectedMethod = $(shippingInputs + ':checked').val();
                $(shippingInputs).each(function() {
                    var id = $(this).val();
                    if (id != selectedMethod) {
                        $(this).closest('li').hide();
                    } else {
                        $(this).closest('li').show();
                    }
                });
            }

            // Initialize on page load
            function initCheckout() {
                var currentDelivery = $(deliverySelect).val() || 'delivery';
                // Set default if no value exists
                if (!$(deliverySelect).val()) {
                    $(deliverySelect).val('delivery');
                }
                // Set corresponding shipping method
                if (currentDelivery == 'pick_up' || currentDelivery == 'dine_in') {
                    setFreeShipping();
                } else {
                    setFlatRate();
                }
            }

            // Run initial setup
            initCheckout();

            // Hide shipping methods after checkout updates
            $(document.body).on('updated_checkout', function() {
                hideUnselectedShipping();
            });

            // Live action event: On Select "delivery_method" change
            $(deliverySelect).change( function () {
                if ($(this).val() == 'pick_up' || $(this).val() == 'dine_in') {
                    setFreeShipping();
                } else {
                    setFlatRate();
                }
            });

            // Live action event: On Shipping method change
            $( 'form.checkout' ).on( 'change', shippingInputs, function() {
                if ($(this).val() != freeShippingVal) {
                    $(deliverySelect).val('delivery');
                    setFlatRate();
                }
            });
        });
    </script>
    <?php
}

关键修改点

  1. 新增initCheckout函数处理页面加载时的默认值设置,避免重复触发change事件
  2. 添加updated_checkout事件监听,在结账更新完成后自动调用hideUnselectedShipping,确保隐藏效果持续
  3. 变量名更具语义化,提升代码可读性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 18:40:22