jQuery变量全局定义但是记录为未定义

时间:2020-12-10 20:23:24

I am making a product image viewer similar to what is on sites like Amazon (you hover over an image, it appears larger -- click the image thumbnail and it sets the main image as what was clicked).

我正在制作一个类似于像亚马逊这样的网站上的产品图像查看器(您将鼠标悬停在图像上,它看起来更大 - 单击图像缩略图,它将主图像设置为点击的内容)。

Background info aside, I set two global variables outside the functions that control the main image. Something strange is happening where the variables are only defined up to a certain point in the code execution, then they become "undefined".

除了背景信息,我在控制主图像的函数之外设置了两个全局变量。有些奇怪的事情发生在变量只被定义到代码执行中的某个点,然后它们变得“未定义”。

Here is my markup:

这是我的标记:

<div id="product-image-gallery">
   <div id="product-image-holder" style="background-image: url('http://example.com/images/main-image.jpg');">My Main Image
   </div>

   <ul>
     <li class="product-thumb">
       <img src="http://example.com/images/image-1.jpg"/>
     </li>
     <li class="product-thumb">
       <img src="http://example.com/images/image-2.jpg"/>
     </li>
   </ul>
</div>

In jQuery, I am storing the original image and image background path in two global variables, then defining the functions that alter the main image container to show the proper image. Here is my jQuery:

在jQuery中,我将原始图像和图像背景路径存储在两个全局变量中,然后定义改变主图像容器以显示正确图像的函数。这是我的jQuery:

var $originalImage = $('#product-image-holder');
var $originalImageSrc = $originalImage.css('background-image');

$('#product-image-gallery ul li.product-thumb').click(function () {
    $('li.product-thumb.active').removeClass('active');
    $(this).addClass('active');
});

$('#product-image-gallery ul li.product-thumb').hover(
//mouseenter event
    function () {
        var $imageChange = $(this).find('img');
        var $imageChangeSrc = 'url(\'' + $imageChange.attr('src') + '\')';
        $originalImage.css("background-image", $imageChangeSrc);
},
//mouseleave event
function () {
    var $activeImage = $('#product-image-gallery ul li.product-thumb.active img');
    var $activeImageSrc = 'url(\'' + $activeImage.attr('src') + '\')';

    if($(this).hasClass('active')){
        return;
    }
    else if ($activeImage != '') {
        $originalImage.css("background-image", $activeImageSrc);
    }
    else {
        $originalImage.css("background-image", $originalImageSrc);
    }
});

When I view the page, all works as expected on mouse hover, except the original image path resets itself to undefined (I can witness this behavior in the console). I am completely stumped as to what could cause this to happen.

当我查看页面时,所有在鼠标悬停时都按预期工作,除了原始图像路径重置为未定义(我可以在控制台中看到此行为)。我完全不知道是什么原因导致这种情况发生。

Any suggestion as to what would make this variable unset itself is greatly appreciated.

非常感谢任何关于什么会使这个变量自行设置的建议。

[EDIT] Here is a jsfiddle with my example, showing the exact same behavior: https://jsfiddle.net/htxxnfuy/

[编辑]这是一个jsfiddle与我的例子,显示完全相同的行为:https://jsfiddle.net/htxxnfuy/

2 个解决方案

#1


You are checking a possible collection of elements against an empty string. When trying to find out if a jQuery selector returns any item (or many), you can test it's length property.

您正在针对空字符串检查可能的元素集合。当试图找出jQuery选择器是否返回任何项目(或多个)时,您可以测试它的length属性。

I've also reduced your code a bit:

我也减少了你的代码:

$(function () {
    // To make your code a bit easier to understand, use $ to prefix
    // only variables that represent a jQuery selector.
    var $originalImage = $('#product-image-holder');
    var originalImageSrc = $originalImage.css('background-image');
    var containerSelector = '#product-image-gallery ul li.product-thumb';
    var $container = $(containerSelector);

    // You can attach as many event handlers as you need in just
    // one go. Also, it's better to use mouseenter and mouseleave
    // instead of hover.
    $container.on({ click: function () {
            $('li.product-thumb.active').removeClass('active');

            $(this).addClass('active');
    }, mouseenter: function () {
        var $imageChange = $(this).find('img');
        var imageChangeSrc = 'url(\'' + $imageChange.attr('src') + '\')';

        $originalImage.css('background-image', imageChangeSrc);
    }, mouseleave: function () {
        var $activeImage = $(containerSelector + '.active img');
        var activeImageSrc = 'url(\'' + $activeImage.attr('src') + '\')';

        // I would review the necessity of this entire check.
        if ($(this).hasClass('active')) {            
        } else if ($activeImage.length > 0) { 
            // If there's at least one element coming
            // from the selector above.           
            $originalImage.css('background-image', activeImageSrc);
        } else {           
            $originalImage.css('background-image', originalImageSrc); 
        }
    }});
});

Demo

#2


You check if .active image found incorrectly. Result is a collection of elements with 0 length if nothing matches selector.

您检查.active图像是否找不正确。如果没有匹配选择器,则结果是具有0长度的元素的集合。

if ($activeImage.length) { // <-- this line
    $originalImage.css("background-image", $activeImageSrc);
}

var $originalImage = $('#product-image-holder');
var $originalImageSrc = $originalImage.css('background-image');

$('#product-image-gallery ul li.product-thumb').click(function () {
    $('li.product-thumb.active').removeClass('active');
    $(this).addClass('active');
});

$('.product-thumb').hover(
//mouseenter event
function () {
    var $imageChange = $(this).find('img');
    var $imageChangeSrc = 'url(\'' + $imageChange.attr('src') + '\')';
    $originalImage.css("background-image", $imageChangeSrc);
},
//mouseleave event
function () {
    var $activeImage = $('li.active img');
    var $activeImageSrc = 'url(\'' + $activeImage.attr('src') + '\')';

    if($(this).hasClass('active')){
        return;
    }
    else if ($activeImage.length) { // <-- this line
        $originalImage.css("background-image", $activeImageSrc);
    }
    else {
        $originalImage.css("background-image", $originalImageSrc);
    }
});
#product-image-holder {
  height: 50px;
  width: 50px;
}
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<div id="product-image-gallery">
   <div id="product-image-holder"
        style="background-image: url('http://placehold.it/50x50');">
     My Main Image
   </div>

   <ul>
     <li class="product-thumb">
       <img src="http://placehold.it/52x52"/>
     </li>
     <li class="product-thumb">
       <img src="http://placehold.it/51x51g"/>
     </li>
   </ul>
</div>

#1


You are checking a possible collection of elements against an empty string. When trying to find out if a jQuery selector returns any item (or many), you can test it's length property.

您正在针对空字符串检查可能的元素集合。当试图找出jQuery选择器是否返回任何项目(或多个)时,您可以测试它的length属性。

I've also reduced your code a bit:

我也减少了你的代码:

$(function () {
    // To make your code a bit easier to understand, use $ to prefix
    // only variables that represent a jQuery selector.
    var $originalImage = $('#product-image-holder');
    var originalImageSrc = $originalImage.css('background-image');
    var containerSelector = '#product-image-gallery ul li.product-thumb';
    var $container = $(containerSelector);

    // You can attach as many event handlers as you need in just
    // one go. Also, it's better to use mouseenter and mouseleave
    // instead of hover.
    $container.on({ click: function () {
            $('li.product-thumb.active').removeClass('active');

            $(this).addClass('active');
    }, mouseenter: function () {
        var $imageChange = $(this).find('img');
        var imageChangeSrc = 'url(\'' + $imageChange.attr('src') + '\')';

        $originalImage.css('background-image', imageChangeSrc);
    }, mouseleave: function () {
        var $activeImage = $(containerSelector + '.active img');
        var activeImageSrc = 'url(\'' + $activeImage.attr('src') + '\')';

        // I would review the necessity of this entire check.
        if ($(this).hasClass('active')) {            
        } else if ($activeImage.length > 0) { 
            // If there's at least one element coming
            // from the selector above.           
            $originalImage.css('background-image', activeImageSrc);
        } else {           
            $originalImage.css('background-image', originalImageSrc); 
        }
    }});
});

Demo

#2


You check if .active image found incorrectly. Result is a collection of elements with 0 length if nothing matches selector.

您检查.active图像是否找不正确。如果没有匹配选择器,则结果是具有0长度的元素的集合。

if ($activeImage.length) { // <-- this line
    $originalImage.css("background-image", $activeImageSrc);
}

var $originalImage = $('#product-image-holder');
var $originalImageSrc = $originalImage.css('background-image');

$('#product-image-gallery ul li.product-thumb').click(function () {
    $('li.product-thumb.active').removeClass('active');
    $(this).addClass('active');
});

$('.product-thumb').hover(
//mouseenter event
function () {
    var $imageChange = $(this).find('img');
    var $imageChangeSrc = 'url(\'' + $imageChange.attr('src') + '\')';
    $originalImage.css("background-image", $imageChangeSrc);
},
//mouseleave event
function () {
    var $activeImage = $('li.active img');
    var $activeImageSrc = 'url(\'' + $activeImage.attr('src') + '\')';

    if($(this).hasClass('active')){
        return;
    }
    else if ($activeImage.length) { // <-- this line
        $originalImage.css("background-image", $activeImageSrc);
    }
    else {
        $originalImage.css("background-image", $originalImageSrc);
    }
});
#product-image-holder {
  height: 50px;
  width: 50px;
}
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<div id="product-image-gallery">
   <div id="product-image-holder"
        style="background-image: url('http://placehold.it/50x50');">
     My Main Image
   </div>

   <ul>
     <li class="product-thumb">
       <img src="http://placehold.it/52x52"/>
     </li>
     <li class="product-thumb">
       <img src="http://placehold.it/51x51g"/>
     </li>
   </ul>
</div>