簡體   English   中英

單擊更改類內的圖像源無法設置未定義的屬性“ src”

[英]Changing source of image inside a class on click Cannot set property 'src' of undefined

我正在嘗試編寫一個非常簡單的代碼,每次單擊圖像時,它都會更改源代碼。 我也希望將圖像懸停顯示,但這將是我可以單擊使它工作的下一步。

這是我的HTML

 <div class="seats-row-A">
                <img id="A1" class="seat-unique" src="chair.svg" >
                <img id="A2" class="seat-unique" src="chair.svg" >
                <img id="A3" class="seat-unique" src="chair.svg" >
                <img id="A4" class="seat-unique"  src="chair.svg" >
                <img id="A5" class="seat-unique" src="chair.svg" >
                <img id="A6" class="seat-unique" src="chair.svg" >
                <img id="A7"  class="seat-unique" src="chair.svg">
</div>

這是我的JS

seatsUnclicked= document.getElementsByClassName("seat-unique");
for(var i = 0; i < seatsUnclicked.length; i++)
    {        
        seatsUnclicked[i].onclick = function(){
        seatsUnclicked[i].src = "chairhover.svg";
    }

}

這是變量范圍的典型問題。在您的情況下,onclick事件將在將來的某個時候發生。到那時,for循環已完成其執行,並且i的值設置為html集合的長度。

之前let的解決方案之一是建立一個立即調用的函數表達式和傳遞的價值i ,這個值將被這種方式與封閉的價值接受為parameter.In i被保留。

在帶有新關鍵字let ES6中,無需創建閉包和IIFE

 var seatsUnclicked = document.getElementsByClassName("seat-unique"); //SOLUTION 1 for (var i = 0; i < seatsUnclicked.length; i++) { (function(x) { seatsUnclicked[x].onclick = function() { seatsUnclicked[x].src = "chairhover.svg"; } }(i)) } //SOLUTION 2 for (let i = 0; i < seatsUnclicked.length; i++) { seatsUnclicked[i].onclick = function() { seatsUnclicked[i].src = "chairhover.svg"; } } 
 <div class="seats-row-A"> <img id="A1" class="seat-unique" src="chair.svg"> <img id="A2" class="seat-unique" src="chair.svg"> <img id="A3" class="seat-unique" src="chair.svg"> <img id="A4" class="seat-unique" src="chair.svg"> <img id="A5" class="seat-unique" src="chair.svg"> <img id="A6" class="seat-unique" src="chair.svg"> <img id="A7" class="seat-unique" src="chair.svg"> </div> 

您可以選擇使用事件傳播 ,而不需要將事件處理程序附加到所有單獨的圖像

 let seatContainer = document.querySelectorAll('.seats-row-A')[0]; // use event-propagation catch all clicks on seats-row-a, and handle clicks that wait seatContainer.addEventListener('click', function(e) { if (!e.target.src) { // no image return; } if (e.target.src.includes('chair.svg')) { e.target.src = 'chairhover.svg'; } else { e.target.src = 'chair.svg'; } }); 
 <div class="seats-row-A"> <img id="A1" class="seat-unique" src="chair.svg" > <img id="A2" class="seat-unique" src="chair.svg" > <img id="A3" class="seat-unique" src="chair.svg" > <img id="A4" class="seat-unique" src="chair.svg" > <img id="A5" class="seat-unique" src="chair.svg" > <img id="A6" class="seat-unique" src="chair.svg" > <img id="A7" class="seat-unique" src="chair.svg"> </div> 

或者,您可以使用let作為聲明來創建i作為塊作用域變量 ,而不是當前的var (函數作用域變量)

for (let i = 0; i < seatsUnclicked.length; i++) {        
    seatsUnclicked[i].onclick = function() {
        seatsUnclicked[i].src = "chairhover.svg";
    }
}

或者,您可以使用事件參數 ,它指向您的元素(有點像第一個示例中的事件傳播)

function handleElementClicked( e ) {
  if (e.target.src.includes('chair.svg')) {
    e.target.src = 'chairhover.svg';
  } else {
    e.target.src = 'chair.svg';
  }
}

for (var i = 0; i < seatsUnclicked.length; i++) {        
    seatsUnclicked[i].onclick = handleElementClicked;
}

或者,您可以索引器綁定到調用函數

for (var i = 0; i < seatsUnclicked.length; i++) {        
    seatsUnclicked[i].onclick = function( index ) {
        seatsUnclicked[index].src = "chairhover.svg";
    }.bind( null, i );
}

getElementsByClassName()方法以NodeList對象的形式返回文檔中具有指定類名的所有元素的集合。

為了避免不必要的類名和內聯onClick js,可以改用querySelectorAll ,並向每個偵聽器添加一個click偵聽器,如下所示:

let seatsUnclicked = document.querySelectorAll("img");

function changeImage() {
this.src="chairhover.svg";
}

seatsUnclicked.forEach(img => {
img.addEventListener('click', changeImage);
})

jsFiddle: https ://jsfiddle.net/AndrewL64/866vf8a1/

我觀察到的幾件事:

  1. 您必須使用setAttribute設置屬性

  2. 在您使用的函數中:seatsUnclicked [i] .src =“ chairhover.svg”;

    在這里我總是等於= SeatsUnclicked.length

    因此它給出了undefined元素。 因此,您將收到錯誤消息,無法設置undefined屬性。

  3. 用戶event.currentTarget.setAttribute:

檢查此https://jsfiddle.net/hgfeh9zw/

<div class="seats-row-A">
<img id="A1" class="seat-unique" 
src="http://icons.iconarchive.com/icons/paomedia/small-n-flat/64/sign-check-icon.png" >
<img id="A2" class="seat-unique" src="http://icons.iconarchive.com/icons/paomedia/small-n-flat/64/sign-check-icon.png" >
<img id="A3" class="seat-unique" src="http://icons.iconarchive.com/icons/paomedia/small-n-flat/64/sign-check-icon.png" >
<img id="A4" class="seat-unique"  src="http://icons.iconarchive.com/icons/paomedia/small-n-flat/64/sign-check-icon.png" >
<img id="A5" class="seat-unique" src="http://icons.iconarchive.com/icons/paomedia/small-n-flat/64/sign-check-icon.png" >
<img id="A6" class="seat-unique" src="http://icons.iconarchive.com/icons/paomedia/small-n-flat/64/sign-check-icon.png" >
<img id="A7"  class="seat-unique" src="http://icons.iconarchive.com/icons/paomedia/small-n-flat/64/sign-check-icon.png">
</div>
<script> 
  window.onload= function(){
  seatsUnclicked= document.getElementsByClassName("seat-unique");
   for(var i = 0; i < seatsUnclicked.length; i++)
   { 
      seatsUnclicked[i].onclick = function(event){
      event.currentTarget.setAttribute('src', 'https://www.gravatar.com/avatar/b43bbab9d16d030a8744f17ca9c1da8d?s=32&d=identicon&r=PG');
    }
  }

 }

  </script>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM