2013-05-15 5 views
1

먼저 스키밍 코드를 사용하십시오.JS에서 addEventListener가 예상대로 작동하지 않습니다.

된 index.html은 다음과 같습니다

<html><head><title>Home</title><script src="js/script.js"></script></head> 
<body onLoad="init()"> 

<ul class="sup" id="sup"> 

    <li class="supitem"> 
     <a href="#" class="supcont">Home<div class="v"></div></a> 
     <ul class="sub"> 
      <li class="subitem"><a href="#" class="subcont">Home1</a></li> 
      <li class="subitem"><a href="#" class="subcont">Home2</a></li> 
      <li class="subitem"><a href="#" class="subcont">Home3</a></li> 
     </ul> 
    </li> 

    <li class="supitem"> 
     <a href="#" class="supcont">Blog<div class="v"></div></a> 
     <ul class="sub"> 
      <li class="subitem"><a href="#" class="subcont">Blog1</a></li> 
      <li class="subitem"><a href="#" class="subcont">Blog2</a></li> 
      <li class="subitem"><a href="#" class="subcont">Blog3</a></li> 
     </ul> 
    </li> 

</ul> 

</body> 
</html> 

script.js이다 : 나는 모든 하위 메뉴 '가시성 전환 할 supermenu를 누를 때 내가하고 싶은 무엇

function init() { 
    var sky = 0; 
    var sup   = document.getElementById("sup"); 
    var supitems = sup.getElementsByClassName("supitem"); 

    for (var i = 0, ln = supitems.length; i < ln; i++) { 
     var supconts = supitems[i].getElementsByClassName("supcont"); 
     var subs = supitems[i].getElementsByClassName("sub"); 
     var supcont = supconts[0]; 

     supcont.innerHTML = "SuperMenu"+i; 

     if (subs.length > 0) { 
      var sub   = subs[0]; 

      supcont.addEventListener("click",function() { 
       toggleVisibility(sub); }); 

      supcont.style.background = "#"+sky+sky+sky; 
      sub.style.background = "#"+sky+sky+sky; 
      sky += 4; 
     } 
    } 
} 

function toggleVisibility(object) { 
    object.style.visibility = 
     (object.style.visibility == "hidden" ?"visible" :"hidden"); 
} 

입니다. 그러나 나는 내가 실수 한 곳을 모른다. Supmenu0을 누르면 Supmenu1의 하위 메뉴가 토글되고 Supmenu1의 하위 메뉴는 토글되지 않습니다. 미리 감사드립니다.

P. 문제는 addEventListener에 있다고 생각합니다.

답변

1

이것은 자주 묻는 질문이지만 내가 발견 한 것보다 더 나은 설명을하려고 노력할 것입니다. 함수를 매개 변수로 전달하면 (이벤트 핸들러를 정의 할 때와 마찬가지로) javascript는 해당 시간에 함수를 평가하지 않고 부모 함수 scope에 대한 함수와 함께 함수를 저장합니다.

이벤트 처리기가 트리거 될 때까지 함수가 평가되지 않습니다. 이때 통역사는 scope 부모의 sub 값을 확인합니다. for 루프가 완료된 이후에도 항상 발생하므로 항상 sub의 마지막 값, 즉 for 루프가 완료되었을 때의 값은 sub입니다. 따라서 모든 이벤트 리스너는 마지막 값인 sub을 사용합니다.

closure을 만들어 원하는 동작을 얻을 수 있습니다. 이 교체 :이와

supcont.addEventListener("click",function() { 
    toggleVisibility(sub); }); 

을 : 우리가 인생을 호출하여 새로운 부모 scope 각 이벤트 핸들러 선언을 포장하기 때문에이 작품

(function(localSub) { 
    supcont.addEventListener("click",function() { 
     toggleVisibility(localSub); 
    });  
})(sub); 

이유입니다. 이렇게하면 이벤트 핸들러가 scope의 복사본을 IIFE 안에 유지하게됩니다 (그 위에 클로저를 만드는 것은 scope이라고합니다). 이제 이벤트 핸들러가 localSub을 찾으면 새로운 부모 인 scope에서 찾으며 원하는 값을 갖게됩니다.

+0

감사합니다. BTW 방금 폐쇄가 무엇인지 배웠습니다. 여기에 링크를 남겨 두는 것이 좋습니다. http://stackoverflow.com/questions/111102/how-do-javascript-closures-work :) –

관련 문제