在商店和存档页面中选择变量时如何更改产品图片?

Posted

技术标签:

【中文标题】在商店和存档页面中选择变量时如何更改产品图片?【英文标题】:How to change product Image when variables are selected in Shop and Archive Pages? 【发布时间】:2021-12-24 14:31:57 【问题描述】:

我使用这个钩子在商店页面上显示变体。但是,选择变量时产品图像不会改变。它适用于单一产品页面。 WordPress 和 php 的新手,我认为 woocommerce 钩子的工作方式类似于“复制和粘贴”。为什么它不适用于商店页面?它如何适用于商店页面?

add_action( 'woocommerce_before_shop_loop', 'show_production_variations_on_shop_page' );
function show_production_variations_on_shop_page() 

remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_single_add_to_cart', 30 );

【问题讨论】:

show_production_variations_on_shop_page() 里面有什么?您也不能混合使用它们传递不同参数的钩子,因此有些适用于档案、类别等,其他适用于购物车,其他适用于单一产品。对于变化,WooCommerce 也使用 JS。使用插件或调试。对于当前示例,没有任何帮助。 感谢@MartinMircev 添加后,它会在商店页面上显示变体选择框、数量字段和添加到购物车按钮。 就像我说的那样,你不能只混合钩子 - woocommerce_template_single_add_to_cart 将执行以下操作 - 根据产品类型加载不同的函数在你的情况下将加载这个 woocommerce_variable_add_to_cart() ,它在其中构建了变体产品表单。 hookr.io/plugins/woocommerce/3.0.6/files/… 。要更新图像,您必须使用 ajax 或加载所有图像并在更改时更新到正确的图像。更新后添加到购物车按钮变量。 非常感谢@MartinMirchev 请问我可以查看哪些模板页面来了解如何为单个产品页面中的可变产品切换图像? 如果你无法调试,你将很难解决它。您可以查看负责在变体选择上更新图像的 js - github.com/woocommerce/woocommerce/blob/trunk/plugins/…。对于模板,您应该使用 content-product.php 及其挂钩来输出您的变体等等 - github.com/woocommerce/woocommerce/blob/trunk/plugins/… 【参考方案1】:

首先,您必须将 woocommerce add-to-cart-variation.js 从商店页面中取出,因为无论您在哪里开发,都需要从您的主题或插件中克隆 add-to-cart-variation.jsenqueue

function add_custom_js()
    
    if( is_shop() )

        wp_dequeue_script( 'wc-add-to-cart-variation' );
        wp_deregister_script( 'wc-add-to-cart-variation' );

        $version = WC_VERSION;

        // Register the script
        wp_register_script( 'wc-add-to-cart-variation', get_template_directory_uri().'/assets/js/add-to-cart-variation.js', array( 'jquery', 'wp-util', 'jquery-blockui' ), $version );
         
        // Localize the script with new data
        
        $params = array(
            'wc_ajax_url'                      => WC_AJAX::get_endpoint( '%%endpoint%%' ),
            'i18n_no_matching_variations_text' => esc_attr__( 'Sorry, no products matched your selection. Please choose a different combination.', 'woocommerce' ),
            'i18n_make_a_selection_text'       => esc_attr__( 'Please select some product options before adding this product to your cart.', 'woocommerce' ),
            'i18n_unavailable_text'            => esc_attr__( 'Sorry, this product is unavailable. Please choose a different combination.', 'woocommerce' ),
        );

        wp_localize_script( 'wc-add-to-cart-variation', 'wc_add_to_cart_variation_params', $params );
         
        // Enqueued script with localized data.
        wp_enqueue_script( 'wc-add-to-cart-variation' );

    


add_action( 'wp_enqueue_scripts', 'add_custom_js', 9999, 1 );

在您正在开发的活动主题或插件中创建一个add-to-cart-variation.js 文件。 (我是主题的enqueueing

在下面添加与woocommerce add-to-cart-variation.js相同的js代码,但我们必须根据需要对其进行修改。

/*global wc_add_to_cart_variation_params */
;(function ( $, window, document, undefined ) 
    /**
     * VariationForm class which handles variation forms and attributes.
     */
    var VariationForm = function( $form ) 
        var self = this;

        self.$form                = $form;
        self.$attributeFields     = $form.find( '.variations select' );
        self.$singleVariation     = $form.find( '.single_variation' );
        self.$singleVariationWrap = $form.find( '.single_variation_wrap' );
        self.$resetVariations     = $form.find( '.reset_variations' );
        self.$product             = $form.closest( '.product' );
        self.variationData        = $form.data( 'product_variations' );
        self.useAjax              = false === self.variationData;
        self.xhr                  = false;
        self.loading              = true;

        // Initial state.
        self.$singleVariationWrap.show();
        self.$form.off( '.wc-variation-form' );

        // Methods.
        self.getChosenAttributes    = self.getChosenAttributes.bind( self );
        self.findMatchingVariations = self.findMatchingVariations.bind( self );
        self.isMatch                = self.isMatch.bind( self );
        self.toggleResetLink        = self.toggleResetLink.bind( self );

        // Events.
        $form.on( 'click.wc-variation-form', '.reset_variations',  variationForm: self , self.onReset );
        $form.on( 'reload_product_variations',  variationForm: self , self.onReload );
        $form.on( 'hide_variation',  variationForm: self , self.onHide );
        $form.on( 'show_variation',  variationForm: self , self.onShow );
        $form.on( 'reset_data',  variationForm: self , self.onResetDisplayedVariation );
        $form.on( 'reset_image',  variationForm: self , self.onResetImage );
        $form.on( 'change.wc-variation-form', '.variations select',  variationForm: self , self.onChange );
        $form.on( 'found_variation.wc-variation-form',  variationForm: self , self.onFoundVariation );
        $form.on( 'check_variations.wc-variation-form',  variationForm: self , self.onFindVariation );
        $form.on( 'update_variation_values.wc-variation-form',  variationForm: self , self.onUpdateAttributes );

        // Init after gallery.
        setTimeout( function() 
            $form.trigger( 'check_variations' );
            $form.trigger( 'wc_variation_form', self );
            self.loading = false;
        , 100 );
    ;

    /**
     * Reset all fields.
     */
    VariationForm.prototype.onReset = function( event ) 
        event.preventDefault();
        event.data.variationForm.$attributeFields.val( '' ).trigger( 'change' );
        event.data.variationForm.$form.trigger( 'reset_data' );
    ;

    /**
     * Reload variation data from the DOM.
     */
    VariationForm.prototype.onReload = function( event ) 
        var form           = event.data.variationForm;
        form.variationData = form.$form.data( 'product_variations' );
        form.useAjax       = false === form.variationData;
        form.$form.trigger( 'check_variations' );
    ;

    /**
     * When a variation is hidden.
     */
    VariationForm.prototype.onHide = function( event ) 
        event.preventDefault();
        event.data.variationForm.$form
            .find( '.single_add_to_cart_button' )
            .removeClass( 'wc-variation-is-unavailable' )
            .addClass( 'disabled wc-variation-selection-needed' );
        event.data.variationForm.$form
            .find( '.woocommerce-variation-add-to-cart' )
            .removeClass( 'woocommerce-variation-add-to-cart-enabled' )
            .addClass( 'woocommerce-variation-add-to-cart-disabled' );
    ;

    /**
     * When a variation is shown.
     */
    VariationForm.prototype.onShow = function( event, variation, purchasable ) 
        event.preventDefault();
        if ( purchasable ) 
            event.data.variationForm.$form
                .find( '.single_add_to_cart_button' )
                .removeClass( 'disabled wc-variation-selection-needed wc-variation-is-unavailable' );
            event.data.variationForm.$form
                .find( '.woocommerce-variation-add-to-cart' )
                .removeClass( 'woocommerce-variation-add-to-cart-disabled' )
                .addClass( 'woocommerce-variation-add-to-cart-enabled' );
         else 
            event.data.variationForm.$form
                .find( '.single_add_to_cart_button' )
                .removeClass( 'wc-variation-selection-needed' )
                .addClass( 'disabled wc-variation-is-unavailable' );
            event.data.variationForm.$form
                .find( '.woocommerce-variation-add-to-cart' )
                .removeClass( 'woocommerce-variation-add-to-cart-enabled' )
                .addClass( 'woocommerce-variation-add-to-cart-disabled' );
        

        // If present, the media element library needs initialized on the variation description.
        if ( wp.mediaelement ) 
            event.data.variationForm.$form.find( '.wp-audio-shortcode, .wp-video-shortcode' )
                .not( '.mejs-container' )
                .filter(
                    function () 
                        return ! $( this ).parent().hasClass( 'mejs-mediaelement' );
                    
                )
                .mediaelementplayer( wp.mediaelement.settings );
        
    ;

    /**
     * When displayed variation data is reset.
     */
    VariationForm.prototype.onResetDisplayedVariation = function( event ) 
        var form = event.data.variationForm;
        form.$product.find( '.product_meta' ).find( '.sku' ).wc_reset_content();
        form.$product
            .find( '.product_weight, .woocommerce-product-attributes-item--weight .woocommerce-product-attributes-item__value' )
            .wc_reset_content();
        form.$product
            .find( '.product_dimensions, .woocommerce-product-attributes-item--dimensions .woocommerce-product-attributes-item__value' )
            .wc_reset_content();
        form.$form.trigger( 'reset_image' );
        form.$singleVariation.slideUp( 200 ).trigger( 'hide_variation' );
    ;

    /**
     * When the product image is reset.
     */
    VariationForm.prototype.onResetImage = function( event ) 
        event.data.variationForm.$form.wc_variations_image_update( false );
    ;

    /**
     * Looks for matching variations for current selected attributes.
     */
    VariationForm.prototype.onFindVariation = function( event, chosenAttributes ) 
        var form              = event.data.variationForm,
            attributes        = 'undefined' !== typeof chosenAttributes ? chosenAttributes : form.getChosenAttributes(),
            currentAttributes = attributes.data;

        if ( attributes.count && attributes.count === attributes.chosenCount ) 
            if ( form.useAjax ) 
                if ( form.xhr ) 
                    form.xhr.abort();
                
                form.$form.block(  message: null, overlayCSS:  background: '#fff', opacity: 0.6   );
                currentAttributes.product_id  = parseInt( form.$form.data( 'product_id' ), 10 );
                currentAttributes.custom_data = form.$form.data( 'custom_data' );
                form.xhr                      = $.ajax( 
                    url: wc_add_to_cart_variation_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'get_variation' ),
                    type: 'POST',
                    data: currentAttributes,
                    success: function( variation ) 
                        if ( variation ) 
                            form.$form.trigger( 'found_variation', [ variation ] );
                         else 
                            form.$form.trigger( 'reset_data' );
                            attributes.chosenCount = 0;

                            if ( ! form.loading ) 
                                form.$form
                                    .find( '.single_variation' )
                                    .after(
                                        '<p class="wc-no-matching-variations woocommerce-info">' +
                                        wc_add_to_cart_variation_params.i18n_no_matching_variations_text +
                                        '</p>'
                                    );
                                form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 );
                            
                        
                    ,
                    complete: function() 
                        form.$form.unblock();
                    
                 );
             else 
                form.$form.trigger( 'update_variation_values' );

                var matching_variations = form.findMatchingVariations( form.variationData, currentAttributes ),
                    variation           = matching_variations.shift();

                if ( variation ) 
                    form.$form.trigger( 'found_variation', [ variation ] );
                 else 
                    form.$form.trigger( 'reset_data' );
                    attributes.chosenCount = 0;

                    if ( ! form.loading ) 
                        form.$form
                            .find( '.single_variation' )
                            .after(
                                '<p class="wc-no-matching-variations woocommerce-info">' +
                                wc_add_to_cart_variation_params.i18n_no_matching_variations_text +
                                '</p>'
                            );
                        form.$form.find( '.wc-no-matching-variations' ).slideDown( 200 );
                    
                
            
         else 
            form.$form.trigger( 'update_variation_values' );
            form.$form.trigger( 'reset_data' );
        

        // Show reset link.
        form.toggleResetLink( attributes.chosenCount > 0 );
    ;

    /**
     * Triggered when a variation has been found which matches all attributes.
     */
    VariationForm.prototype.onFoundVariation = function( event, variation ) 
        var form           = event.data.variationForm,
            $sku           = form.$product.find( '.product_meta' ).find( '.sku' ),
            $weight        = form.$product.find(
                '.product_weight, .woocommerce-product-attributes-item--weight .woocommerce-product-attributes-item__value'
            ),
            $dimensions    = form.$product.find(
                '.product_dimensions, .woocommerce-product-attributes-item--dimensions .woocommerce-product-attributes-item__value'
            ),
            $qty           = form.$singleVariationWrap.find( '.quantity' ),
            purchasable    = true,
            variation_id   = '',
            template       = false,
            $template_html = '';

        if ( variation.sku ) 
            $sku.wc_set_content( variation.sku );
         else 
            $sku.wc_reset_content();
        

        if ( variation.weight ) 
            $weight.wc_set_content( variation.weight_html );
         else 
            $weight.wc_reset_content();
        

        if ( variation.dimensions ) 
            // Decode HTML entities.
            $dimensions.wc_set_content( $.parseHTML( variation.dimensions_html )[0].data );
         else 
            $dimensions.wc_reset_content();
        

        form.$form.wc_variations_image_update( variation );

        if ( ! variation.variation_is_visible ) 
            template = wp_template( 'unavailable-variation-template' );
         else 
            template     = wp_template( 'variation-template' );
            variation_id = variation.variation_id;
        

        $template_html = template( 
            variation: variation
         );
        $template_html = $template_html.replace( '/*<![CDATA[*/', '' );
        $template_html = $template_html.replace( '/*]]>*/', '' );

        form.$singleVariation.html( $template_html );
        form.$form.find( 'input[name="variation_id"], input.variation_id' ).val( variation.variation_id ).trigger( 'change' );

        // Hide or show qty input
        if ( variation.is_sold_individually === 'yes' ) 
            $qty.find( 'input.qty' ).val( '1' ).attr( 'min', '1' ).attr( 'max', '' ).trigger( 'change' );
            $qty.hide();
         else 

            var $qty_input = $qty.find( 'input.qty' ),
                qty_val    = parseFloat( $qty_input.val() );

            if ( isNaN( qty_val ) ) 
                qty_val = variation.min_qty;
             else 
                qty_val = qty_val > parseFloat( variation.max_qty ) ? variation.max_qty : qty_val;
                qty_val = qty_val < parseFloat( variation.min_qty ) ? variation.min_qty : qty_val;
            

            $qty_input.attr( 'min', variation.min_qty ).attr( 'max', variation.max_qty ).val( qty_val ).trigger( 'change' );
            $qty.show();
        

        // Enable or disable the add to cart button
        if ( ! variation.is_purchasable || ! variation.is_in_stock || ! variation.variation_is_visible ) 
            purchasable = false;
        

        // Reveal
        if ( form.$singleVariation.text().trim() ) 
            form.$singleVariation.slideDown( 200 ).trigger( 'show_variation', [ variation, purchasable ] );
         else 
            form.$singleVariation.show().trigger( 'show_variation', [ variation, purchasable ] );
        
    ;

    /**
     * Triggered when an attribute field changes.
     */
    VariationForm.prototype.onChange = function( event ) 
        var form = event.data.variationForm;

        form.$form.find( 'input[name="variation_id"], input.variation_id' ).val( '' ).trigger( 'change' );
        form.$form.find( '.wc-no-matching-variations' ).remove();

        if ( form.useAjax ) 
            form.$form.trigger( 'check_variations' );
         else 
            form.$form.trigger( 'woocommerce_variation_select_change' );
            form.$form.trigger( 'check_variations' );
        

        // Custom event for when variation selection has been changed
        form.$form.trigger( 'woocommerce_variation_has_changed' );
    ;

    /**
     * Escape quotes in a string.
     * @param string string
     * @return string
     */
    VariationForm.prototype.addSlashes = function( string ) 
        string = string.replace( /'/g, '\\\'' );
        string = string.replace( /"/g, '\\\"' );
        return string;
    ;

    /**
     * Updates attributes in the DOM to show valid values.
     */
    VariationForm.prototype.onUpdateAttributes = function( event ) 
        var form              = event.data.variationForm,
            attributes        = form.getChosenAttributes(),
            currentAttributes = attributes.data;

        if ( form.useAjax ) 
            return;
        

        // Loop through selects and disable/enable options based on selections.
        form.$attributeFields.each( function( index, el ) 
            var current_attr_select     = $( el ),
                current_attr_name       = current_attr_select.data( 'attribute_name' ) || current_attr_select.attr( 'name' ),
                show_option_none        = $( el ).data( 'show_option_none' ),
                option_gt_filter        = ':gt(0)',
                attached_options_count  = 0,
                new_attr_select         = $( '<select/>' ),
                selected_attr_val       = current_attr_select.val() || '',
                selected_attr_val_valid = true;

            // Reference options set at first.
            if ( ! current_attr_select.data( 'attribute_html' ) ) 
                var refSelect = current_attr_select.clone();

                refSelect.find( 'option' ).removeAttr( 'attached' ).prop( 'disabled', false ).prop( 'selected', false );

                // Legacy data attribute.
                current_attr_select.data(
                    'attribute_options',
                    refSelect.find( 'option' + option_gt_filter ).get()
                );
                current_attr_select.data( 'attribute_html', refSelect.html() );
            

            new_attr_select.html( current_attr_select.data( 'attribute_html' ) );

            // The attribute of this select field should not be taken into account when calculating its matching variations:
            // The constraints of this attribute are shaped by the values of the other attributes.
            var checkAttributes = $.extend( true, , currentAttributes );

            checkAttributes[ current_attr_name ] = '';

            var variations = form.findMatchingVariations( form.variationData, checkAttributes );

            // Loop through variations.
            for ( var num in variations ) 
                if ( typeof( variations[ num ] ) !== 'undefined' ) 
                    var variationAttributes = variations[ num ].attributes;

                    for ( var attr_name in variationAttributes ) 
                        if ( variationAttributes.hasOwnProperty( attr_name ) ) 
                            var attr_val         = variationAttributes[ attr_name ],
                                variation_active = '';

                            if ( attr_name === current_attr_name ) 
                                if ( variations[ num ].variation_is_active ) 
                                    variation_active = 'enabled';
                                

                                if ( attr_val ) 
                                    // Decode entities.
                                    attr_val = $( '<div/>' ).html( attr_val ).text();

                                    // Attach to matching options by value. This is done to compare
                                    // TEXT values rather than any HTML entities.
                                    var $option_elements = new_attr_select.find( 'option' );
                                    if ( $option_elements.length ) 
                                        for (var i = 0, len = $option_elements.length; i < len; i++) 
                                            var $option_element = $( $option_elements[i] ),
                                                option_value = $option_element.val();

                                            if ( attr_val === option_value ) 
                                                $option_element.addClass( 'attached ' + variation_active );
                                                break;
                                            
                                        
                                    
                                 else 
                                    // Attach all apart from placeholder.
                                    new_attr_select.find( 'option:gt(0)' ).addClass( 'attached ' + variation_active );
                                
                            
                        
                    
                
            

            // Count available options.
            attached_options_count = new_attr_select.find( 'option.attached' ).length;

            // Check if current selection is in attached options.
            if ( selected_attr_val ) 
                selected_attr_val_valid = false;

                if ( 0 !== attached_options_count ) 
                    new_attr_select.find( 'option.attached.enabled' ).each( function() 
                        var option_value = $( this ).val();

                        if ( selected_attr_val === option_value ) 
                            selected_attr_val_valid = true;
                            return false; // break.
                        
                    );
                
            

            // Detach the placeholder if:
            // - Valid options exist.
            // - The current selection is non-empty.
            // - The current selection is valid.
            // - Placeholders are not set to be permanently visible.
            if ( attached_options_count > 0 && selected_attr_val && selected_attr_val_valid && ( 'no' === show_option_none ) ) 
                new_attr_select.find( 'option:first' ).remove();
                option_gt_filter = '';
            

            // Detach unattached.
            new_attr_select.find( 'option' + option_gt_filter + ':not(.attached)' ).remove();

            // Finally, copy to DOM and set value.
            current_attr_select.html( new_attr_select.html() );
            current_attr_select.find( 'option' + option_gt_filter + ':not(.enabled)' ).prop( 'disabled', true );

            // Choose selected value.
            if ( selected_attr_val ) 
                // If the previously selected value is no longer available, fall back to the placeholder (it's going to be there).
                if ( selected_attr_val_valid ) 
                    current_attr_select.val( selected_attr_val );
                 else 
                    current_attr_select.val( '' ).trigger( 'change' );
                
             else 
                current_attr_select.val( '' ); // No change event to prevent infinite loop.
            
        );

        // Custom event for when variations have been updated.
        form.$form.trigger( 'woocommerce_update_variation_values' );
    ;

    /**
     * Get chosen attributes from form.
     * @return array
     */
    VariationForm.prototype.getChosenAttributes = function() 
        var data   = ;
        var count  = 0;
        var chosen = 0;

        this.$attributeFields.each( function() 
            var attribute_name = $( this ).data( 'attribute_name' ) || $( this ).attr( 'name' );
            var value          = $( this ).val() || '';

            if ( value.length > 0 ) 
                chosen ++;
            

            count ++;
            data[ attribute_name ] = value;
        );

        return 
            'count'      : count,
            'chosenCount': chosen,
            'data'       : data
        ;
    ;

    /**
     * Find matching variations for attributes.
     */
    VariationForm.prototype.findMatchingVariations = function( variations, attributes ) 
        var matching = [];
        for ( var i = 0; i < variations.length; i++ ) 
            var variation = variations[i];

            if ( this.isMatch( variation.attributes, attributes ) ) 
                matching.push( variation );
            
        
        return matching;
    ;

    /**
     * See if attributes match.
     * @return Boolean
     */
    VariationForm.prototype.isMatch = function( variation_attributes, attributes ) 
        var match = true;
        for ( var attr_name in variation_attributes ) 
            if ( variation_attributes.hasOwnProperty( attr_name ) ) 
                var val1 = variation_attributes[ attr_name ];
                var val2 = attributes[ attr_name ];
                if ( val1 !== undefined && val2 !== undefined && val1.length !== 0 && val2.length !== 0 && val1 !== val2 ) 
                    match = false;
                
            
        
        return match;
    ;

    /**
     * Show or hide the reset link.
     */
    VariationForm.prototype.toggleResetLink = function( on ) 
        if ( on ) 
            if ( this.$resetVariations.css( 'visibility' ) === 'hidden' ) 
                this.$resetVariations.css( 'visibility', 'visible' ).hide().fadeIn();
            
         else 
            this.$resetVariations.css( 'visibility', 'hidden' );
        
    ;

    /**
     * Function to call wc_variation_form on jquery selector.
     */
    $.fn.wc_variation_form = function() 
        new VariationForm( this );
        return this;
    ;

    /**
     * Stores the default text for an element so it can be reset later
     */
    $.fn.wc_set_content = function( content ) 
        if ( undefined === this.attr( 'data-o_content' ) ) 
            this.attr( 'data-o_content', this.text() );
        
        this.text( content );
    ;

    /**
     * Stores the default text for an element so it can be reset later
     */
    $.fn.wc_reset_content = function() 
        if ( undefined !== this.attr( 'data-o_content' ) ) 
            this.text( this.attr( 'data-o_content' ) );
        
    ;

    /**
     * Stores a default attribute for an element so it can be reset later
     */
    $.fn.wc_set_variation_attr = function( attr, value ) 
        if ( undefined === this.attr( 'data-o_' + attr ) ) 
            this.attr( 'data-o_' + attr, ( ! this.attr( attr ) ) ? '' : this.attr( attr ) );
        
        if ( false === value ) 
            this.removeAttr( attr );
         else 
            this.attr( attr, value );
        
    ;

    /**
     * Reset a default attribute for an element so it can be reset later
     */
    $.fn.wc_reset_variation_attr = function( attr ) 
        if ( undefined !== this.attr( 'data-o_' + attr ) ) 
            this.attr( attr, this.attr( 'data-o_' + attr ) );
        
    ;

    /**
     * Sets product images for the chosen variation
     */
    $.fn.wc_variations_image_update = function( variation ) 

        var $form             = this,
            $product          = $form.closest( '.product' ),

            $product_gallery  = $product.find( '.images' ),
            $gallery_nav      = $product.find( '.flex-control-nav' ),
            $gallery_img      = $gallery_nav.find( 'li:eq(0) img' ),
            $product_img_wrap = $product
                .find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder, .woocommerce-loop-product__link' )
                .eq( 0 ),
            $product_img      = $product_img_wrap.find( '.wp-post-image' ),
            $product_link     = $product_img_wrap.find( 'a' ).eq( 0 );

        if ( variation && variation.image && variation.image.src && variation.image.src.length > 1 ) 
            // See if the gallery has an image with the same original src as the image we want to switch to.
            var galleryHasImage = $gallery_nav.find( 'li img[data-o_src="' + variation.image.gallery_thumbnail_src + '"]' ).length > 0;

            // If the gallery has the image, reset the images. We'll scroll to the correct one.
            if ( galleryHasImage ) 
                $form.wc_variations_image_reset();
            

            // See if gallery has a matching image we can slide to.
            var slideToImage = $gallery_nav.find( 'li img[src="' + variation.image.gallery_thumbnail_src + '"]' );

            if ( slideToImage.length > 0 ) 
                slideToImage.trigger( 'click' );
                $form.attr( 'current-image', variation.image_id );
                window.setTimeout( function() 
                    $( window ).trigger( 'resize' );
                    $product_gallery.trigger( 'woocommerce_gallery_init_zoom' );
                , 20 );
                return;
            

            $product_img.wc_set_variation_attr( 'src', variation.image.src );
            $product_img.wc_set_variation_attr( 'height', variation.image.src_h );
            $product_img.wc_set_variation_attr( 'width', variation.image.src_w );
            $product_img.wc_set_variation_attr( 'srcset', variation.image.srcset );
            $product_img.wc_set_variation_attr( 'sizes', variation.image.sizes );
            $product_img.wc_set_variation_attr( 'title', variation.image.title );
            $product_img.wc_set_variation_attr( 'data-caption', variation.image.caption );
            $product_img.wc_set_variation_attr( 'alt', variation.image.alt );
            $product_img.wc_set_variation_attr( 'data-src', variation.image.full_src );
            $product_img.wc_set_variation_attr( 'data-large_image', variation.image.full_src );
            $product_img.wc_set_variation_attr( 'data-large_image_width', variation.image.full_src_w );
            $product_img.wc_set_variation_attr( 'data-large_image_height', variation.image.full_src_h );
            $product_img_wrap.wc_set_variation_attr( 'data-thumb', variation.image.src );
            $gallery_img.wc_set_variation_attr( 'src', variation.image.gallery_thumbnail_src );
            $product_link.wc_set_variation_attr( 'href', variation.image.full_src );
         else 
            $form.wc_variations_image_reset();
        

        window.setTimeout( function() 
            $( window ).trigger( 'resize' );
            $product_gallery.trigger( 'woocommerce_gallery_init_zoom' );
        , 20 );
    ;

    /**
     * Reset main image to defaults.
     */
    $.fn.wc_variations_image_reset = function() 
        var $form             = this,
            $product          = $form.closest( '.product' ),
            $product_gallery  = $product.find( '.images' ),
            $gallery_nav      = $product.find( '.flex-control-nav' ),
            $gallery_img      = $gallery_nav.find( 'li:eq(0) img' ),
            $product_img_wrap = $product
                .find( '.woocommerce-product-gallery__image, .woocommerce-product-gallery__image--placeholder, .woocommerce-loop-product__link' )
                .eq( 0 ),
            $product_img      = $product_img_wrap.find( '.wp-post-image' ),
            $product_link     = $product_img_wrap.find( 'a' ).eq( 0 );

        $product_img.wc_reset_variation_attr( 'src' );
        $product_img.wc_reset_variation_attr( 'width' );
        $product_img.wc_reset_variation_attr( 'height' );
        $product_img.wc_reset_variation_attr( 'srcset' );
        $product_img.wc_reset_variation_attr( 'sizes' );
        $product_img.wc_reset_variation_attr( 'title' );
        $product_img.wc_reset_variation_attr( 'data-caption' );
        $product_img.wc_reset_variation_attr( 'alt' );
        $product_img.wc_reset_variation_attr( 'data-src' );
        $product_img.wc_reset_variation_attr( 'data-large_image' );
        $product_img.wc_reset_variation_attr( 'data-large_image_width' );
        $product_img.wc_reset_variation_attr( 'data-large_image_height' );
        $product_img_wrap.wc_reset_variation_attr( 'data-thumb' );
        $gallery_img.wc_reset_variation_attr( 'src' );
        $product_link.wc_reset_variation_attr( 'href' );
    ;

    $(function() 
        if ( typeof wc_add_to_cart_variation_params !== 'undefined' ) 
            $( '.variations_form' ).each( function() 
                $( this ).wc_variation_form();
            );
        
    );

    /**
     * Avoids using wp.template where possible in order to be CSP compliant.
     * wp.template uses internally eval().
     * @param string templateId
     * @return Function
     */
    var wp_template = function( templateId ) 
        var html = document.getElementById( 'tmpl-' + templateId ).textContent;
        var hard = false;
        // any <# #> interpolate (evaluate).
        hard = hard || /<#\s?data\./.test( html );
        // any data that is NOT data.variation.
        hard = hard || /?\s?data\.(?!variation\.).+?/.test( html );
        // any data access deeper than 1 level e.g.
        // data.variation.object.item
        // data.variation.object['item']
        // data.variation.array[0]
        hard = hard || /?\s?data\.variation\.[\w-]*[^\s]/.test ( html );
        if ( hard ) 
            return wp.template( templateId );
        
        return function template ( data ) 
            var variation = data.variation || ;
            return html.replace( /(?)\s?data\.variation\.([\w-]*)\s?(?)/g, function( _, open, key, close ) 
                // Error in the format, ignore.
                if ( open.length !== close.length ) 
                    return '';
                
                var replacement = variation[ key ] || '';
                //   => interpolate (unescaped).
                //     => interpolate (escaped).
                // https://codex.wordpress.org/javascript_Reference/wp.template
                if ( open.length === 2 ) 
                    return window.escape( replacement );
                
                return replacement;
            );
        ;
    ;

)( jQuery, window, document );

经过测试并且有效。

【讨论】:

谢谢@Bhautik。它对我不起作用。为了快速测试,我测试了 20。将您的add-to-cart-variation.js 复制并粘贴到主题的/js/add-to-cart-variation.js。将此行从您的函数 /assets/js/add-to-cart-variation.js 更改为 /js/add-to-cart-variation.js 以反映 js 文件的正确目录。在functions.php 中插入函数。没有错误,但它不起作用。 可以分享一下网址吗? 抱歉,应该修复了。 已修复。请检查并告诉我。 add-to-cart-variation.js

以上是关于在商店和存档页面中选择变量时如何更改产品图片?的主要内容,如果未能解决你的问题,请参考以下文章

如何删除 Woocommerce 商店页面上的简短描述

WooCommerce 类别/标签存档-“未找到产品”

单个产品页面上的 Woocommerce 钩子溢出

在 WooCommerce 存档产品页面上更改分页基础 slug

单击时从数据库中更改图片?

用 WooCommerce 3 中选择的变化价格替换可变价格范围