2013-07-08 2 views
0

addEventListener()을 사용한 적이 없지만 각자 원하는 HTML을 작성할 수 없습니다. <div> 콘텐츠를 생성하는 방식 때문에 버튼으로 처리됩니다. 등가은 다음과 같습니다JavaScript가 addEventListener()가 예상대로 작동하지 않습니다.

<div onmousedown="jsItems[someId].toggleImage(someGallery, someIndex);"></div> 

은 내가 노력했습니다 것은 이것이다 :

JsTree.prototype.addGalleries = function(inElements) { 
    // ...unrelated code here removed for StackOverflow... 

    for (var i = 0; i < this.jsGalleries.length; i++) { 
     for (var j = 0; j < this.jsGalleries[i].buttons.length; j++) { 
      var self = this; 
      this.jsGalleries[i].buttons[j].addEventListener("mousedown", function() { 
       self.toggleImage(i, j); 
      }); 
     } 
    } 
} 

경우 0 1-i 수와 0 2-j 카운트 (이 경우 두 i에 대한) , ijsomeIndex 나타내고, I는 상기 (나 addEventListener의 함수 내 self.id 함께) 코드와 내부 this.idsomeId 액세스 수 someGallery 나타낸다. 항상 경고 것을

JsTree.prototype.toggleImage = function(inGallery, inIndex) { 
    alert(this.id+", "+inGallery+", "+inIndex); 
} 

"8, 2, 3"관계가있는 버튼을 클릭 :

문제는 이러한 "버튼"중 하나 (<div>들)을 클릭하는 것으로는하지만 트리거 점이다. "8"은 맞지만 "2"또는 "3"으로 경고하는 이유를 알지 못합니다. 그것들은 ij에 (이 "8, 2, 2"로 경고하는 것으로 확인 됨으로써) 검증 된 것보다 1 더 많은 것 같습니다.

편집 : someId, someGallerysomeIndex 실제 변수가되지 않습니다, 그들은 내가 문제를 설명하려고 만들어 정크입니다.

답변

3

이것은 고전적인 JS 실수입니다. 문제는 ij의 값이 모든 함수 범위에서 캡처되지 않으며 이벤트 처리기가 비동기라는 점입니다. 즉, 이벤트 핸들러가 실행될 때 for 루프가 완료 될 때까지 실행되었으므로 i == this.jsGalleries.lengthj === this.jsGalleries[this.jsGalleries.length - 1].buttons.length입니다.

다음 중 하나를 사용 해보세요 :

가능성이
JsTree.prototype.addGalleries = function(inElements) { 
    // ...unrelated code here removed for StackOverflow... 

    for (var i = 0; i < this.jsGalleries.length; i++) { 
    for (var j = 0; j < this.jsGalleries[i].buttons.length; j++) { 
     (function(self, innerI, innerJ){ 
     var galleryEl = self.jsGalleries[innerI].buttons[innerJ]; 
     galleryEl.addEventListener("mousedown", function() { 
      self.toggleImage(innerI, innerJ); 
     }); 
     })(this, i, j); 
    } 
    } 
} 

또는 명확가 :

JsTree.prototype.addGalleries = function(inElements) { 
    // ...unrelated code here removed for StackOverflow... 

    var addHandler = function(self, i, j){ 
    self.jsGalleries[i].buttons[j].addEventListener("mousedown", function() { 
     self.toggleImage(i, j); 
    }); 
    }; 

    for (var i = 0; i < this.jsGalleries.length; i++) { 
    for (var j = 0; j < this.jsGalleries[i].buttons.length; j++) { 
     addHandler(this, i, j); 
    } 
    } 
} 
+0

감사합니다. 두 번째 해결 방법이 더 쉽게 이해 될 것이라고 생각합니다. – asimes

+0

두 번째 해결 방법을 이해 했으므로 작동했습니다. 감사합니다. – asimes

1

그것은하여 addEventListener에 문제가 아니에요. 이것은 흔한 실수입니다. 무슨 일이 벌어지고 있는지 이해하기 위해서 클로저가 어떻게 작동하는지 설명해야합니다.

var i = 5; 
while(i--){ 
    setTimeout(function(){ 
    console.log(i); 
    }, 100); 
} 

각 함수는 변수 i 참조 주어진다 :

가 루프 및 그 안에 기능을

. 즉, 값을 정의한 시점에 i의 값을 유지하지 않습니다. 다시 말하지만, 각 함수에는 함수가 선언 된 시점의 값이 아닌 동일한 변수 i에 대한 참조가 있습니다. 위의 예제에서 모든 setTimeout은 비동기 적으로 정의됩니다. 익명 함수는 모두 100 밀리 초에 시작되며 함수가 실행될 때 각각의 값은 i에 기록됩니다. 나의 예에서, 그 값은 모든 함수에 대해 -1이 될 것이다.

이 문제를 해결하는 방법은 두 가지가 있습니다.당신이 실제 DOM 요소에 값을 저장하고, 여기에

for (var i = 0; i < this.jsGalleries.length; i++) { 
    for (var j = 0; j < this.jsGalleries[i].buttons.length; j++) { 
     var self = this; 
     self.gallery = {i: i, j: j}; 
     this.jsGalleries[i].buttons[j].addEventListener("mousedown", function() { 
      self.toggleImage(self.gallery.i, self.gallery.j); 
     }); 
    } 
} 

: 나는 당신에게 먼저 쉽게 하나를 보여 드리겠습니다. 이 값은 루프를 실행 한 시점의 값과 동일하므로 이벤트 리스너가 올바른 값을 가져옵니다. 갤러리라는 객체의 값을 중첩했습니다. 나는 그것을 네임 스페이스의 종류로 만들었습니다. 브라우저가 동일한 이름의 속성을 구현하는 경우를 대비하여 DOM의 요소에 값을 저장하는 것은 좋지 않습니다. 나는 갤러리가 충분히 안전하다고 느낀다.

이 문제를 해결하기위한 또 다른 옵션은 아마도 이점을 활용하여 클로저를 사용하는 것입니다.

이 경우에는 리스너를 만들 때 즉시 실행되는 자체 실행 함수 (예 : 클로저)를 만듭니다. 다시 말해서,이 함수는 리스너가 추가 될 때 실행되고, 실행될 때 실행되지 않습니다. 이렇게하는 이유는 나중에 self, i, j와 같이 저장하기 원하는 값을 전달할 수 있기 때문입니다. 그런 다음 이벤트가 발생하면 ACTUALLY가 실행되는 함수가 내부 함수 (actualListener)입니다. actualListener에는 클로저 함수가 실행될 때 클로저에 저장된 모든 값의 복사본이 있습니다.

+0

지금 문제를 이해하고 있습니다. 감사합니다. 솔루션을 이해하는 데 잠시 시간을 할애해야 겠지만, 몇 번 읽어 보겠습니다. 하하하. – asimes

+0

다른 솔루션을 추가하고 있습니다. 아마도이 솔루션을 사용하고 싶을 것입니다. 여기서 잠깐 나눌거야 ;-) – THEtheChad

+0

함수의'}'끝에'(self, i, j)'를 이해하지 못한다. 그 얘기 좀 해줄 수 있니? – asimes

관련 문제