2014-12-26 73 views
5

我在使用JavaScript定向動態創建的元素時遇到了一些問題。有關動態創建的HTML的事件的JavaScript問題

問題1

縮短JavaScript代碼:

var lightbox = document.createElement('div'), 
    nav = document.createElement("nav"), 
    imga = document.querySelectorAll(".gallery a"); 
for (i = 0; i < imga.length; i++) { 
    imga[i].addEventListener("click", function() { 
     document.body.insertBefore(lightbox, document.body.firstChild); 
     lightbox.appendChild(nav); 
    }); 
} 

1:現在我要讓我的<nav>的事件。我如何獲得該活動的目標是#lightbox nav a而不僅僅是#lightbox nav

nav.addEventListener("click", function() { 
    // works, but I want to target only the <a> links inside 
}); 

我試過很多東西,像這樣:

var selector = document.querySelectorAll("nav a"); 
for (i = 0; i < selector.length; i++) { 
    selector[i].addEventListener("click", function() { 
     // doesn't work because the <nav> is inserted dynamically 
    }); 
} 

這:

var selector = nav.getElementsByTagName("a"); 
for (i = 0; i < selector.length; i++) { 
    selector[i].addEventListener("click", function() { 
     // doesn't work because the <nav> is inserted dynamically 
    }); 
} 

第2期

縮短JavaScript代碼:

var img, 
    imga = document.querySelectorAll(".gallery a"); 
for (i = 0; i < imga.length; i++) { 
    imga[i].addEventListener("click", function() { 
      for (i = 0; i < imga.length; i++) { 
       img = document.createElement("img"); 
       lightbox.appendChild(img); 
      } 
    }); 
} 

2:如何將事件添加到動態創建的#lightbox img?該img = document.createElement("img")必須追加多個圖像的功能裏面,因爲這個原因,我不能做這樣的(就像目前<nav>):

img.addEventListener("click", function() { 
    // doesn't work because img = document.createElement("img") 
    // has to be inside another function 
}); 

有人可以請幫我在這?我在JavaScript方面經驗不足。

+0

這是很好的問題。 +1 –

回答

0

就我而言,解決方案並不難。隨着@adeneo讓我想想嵌套的事件處理程序,它竟然就好了工作 - 我能夠用我所有的選擇,而不修改:

var lightbox = document.createElement('div'), 
    nav = document.createElement("nav"), 
    imga = document.querySelectorAll(".gallery a"), 
    gallery = document.getElementsByClassName("gallery"), 
    img; 
for (i = 0; i < imga.length; i++) { 
    imga[i].addEventListener("click", function() { 
     lightbox.appendChild(nav); 
     document.body.insertBefore(lightbox, document.body.firstChild); 
     for (i = 0; i < imga.length; i++) { 
      img = document.createElement("img"); 
      lightbox.appendChild(img); 
     } 
     lightbox.addEventListener("click", function() { 
      // works fine 
     }); 
     var nava = document.querySelectorAll("#lightbox nav a"); 
     for (i = 0; i < nava.length; i++) { 
      nava[i].addEventListener("click", function() { 
       // works fine 
      }); 
     } 
     var limg = document.querySelectorAll("#lightbox img"); 
     for (i = 0; i < limg.length; i++) { 
      limg[i].addEventListener("click", function() { 
       // works fine 
      }); 
     } 
    }); 
} 
+0

Next Up ... [Promises](http://blog.millermedeiros.com/callbacks-promises-signals-and-events/) –

+0

@EddieB我還沒有讀過什麼承諾實際上是否可以實施我的情況? – mnsth

3

問題2

簡單的解決方法是向事件處理程序添加到所有元素內循環

var img, 
    imga = document.querySelectorAll(".gallery a"); 

for (i = 0; i < imga.length; i++) { 
    imga[i].addEventListener("click", function() { 
     for (i = 0; i < imga.length; i++) { 
      img = document.createElement("img"); 
      img.setAttribute("src", imga[i].getAttribute("href")); 
      lightbox.appendChild(img); 

      img.addEventListener('click', fn, false); 
     } 
    }); 
} 

的稍硬的解決方案是使用委託的事件處理程序

var img, 
    imga = document.querySelectorAll(".gallery a"); 

lightbox.addEventListener('click', function(e) { 
    if (e.target.nodeType.toLowerCase() === 'img') { 
     // do stuff 
    } 
}, false); 

for (i = 0; i < imga.length; i++) { 
    imga[i].addEventListener("click", function() { 
     for (i = 0; i < imga.length; i++) { 
      img = document.createElement("img"); 
      img.setAttribute("src", imga[i].getAttribute("href")); 
      lightbox.appendChild(img); 
     } 
    }); 
} 

問題1

可以像上面那樣解決,委託事件ha ndler

nav.addEventListener("click", function(e) { 
    if (e.target.nodeType.toLowerCase() === 'a') { 

     // an achor was clicked, do stuff 

    } 
}); 
+0

感謝您的回覆。你的「委託事件處理程序」看起來不太優雅,沒有更好的解決方案?而且,如果我在這些if語句中放入諸如'e.stopPropagation()'和'this'之類的東西,它們會以什麼爲目標?除此之外,這個陳述依賴於函數選擇器,對吧? – mnsth

+0

如果你想更優雅,你應該仔細觀察jQuery是如何做到的。 jQuery在事件處理程序中將'event.target'綁定爲'this',以便'this'實際上成爲動態元素等等。因此,可以創建比檢查'nodeType'更好看的易用性函數。然而,原則上,這正是jQuery和其他庫所做的,它們依賴於冒泡將事件處理程序附加到父元素,然後檢查event.target中DOM樹上的任何元素是否匹配某個字符串選擇器等。 – adeneo

+0

不幸的是,我不能編寫一個完整的選擇器引擎和事件處理庫作爲答案,我只能向您展示委派的事件處理程序是如何在原則上工作的,而且您必須花費所有的時間來完成適合您需求的事情。 – adeneo