2012-05-30 7 views
2

Backbone Marionette CompositeView를 사용하여 만든 간단한 테이블이 있습니다. 이 표의 유일한 요구 사항은 데이터를 표시하고 사용자가 헤더 행을 클릭하여 정렬 할 수있게하는 것입니다. 표를 정렬 할 때 헤더 열을 정렬하는 데 사용되는 열에는 CSS (예 : 'class = "sort asc"')를 사용하여 화살표를 표시 할 수 있도록 클래스가 태그로 지정됩니다.백본 Marionette CompositeView "Event Zombie"

여기에 문제가 있습니다. 헤더 행을 클릭하면 콜백에 전달되는 요소 (event.target을 통해)는 DOM에있는 테이블의 일부가 아닙니다. 대신 Chrome의 디버깅 도구를 사용하면 대상 요소가 실제로 템플릿 스크립트 블록의 일부이며 사용자가 실제로 보는 요소가 아닌 것처럼 보입니다.

지금 당장 가장 좋은 방법은 템플릿의 복제본에서 고유 한 정보를 검색하여 DOM에 실제로 연결된 요소를 조회하는 것입니다.

여기 복합 뷰 코드이다 (하나 빌린 Derick 베일리 샘플 바이올린의)

// The grid view 
var GridView = Backbone.Marionette.CompositeView.extend({ 
    tagName: "table", 
    template: "#grid-template", 
    itemView: GridRow, 

    events: { 
     'click th': 'doSort' 
    }, 

    doSort: function(event) { 
     var target = $(event.target); 
     this.collection.sortByField(target.data('sortby')); 

     target.parent('tr').find('.sort').removeAttr('class'); 
     target.addClass('sort ' + this.collection.sortdir); 
     debugger; // NOTE: no change to elements in the DOM. WTH? 

     target = this.$('[data-sortby=' + target.data('sortby') + ']'); 
     target.parent('tr').find('.sort').removeAttr('class'); 
     target.addClass('sort ' + this.collection.sortdir); 
     debugger; // NOTE: DOM updated. 
    }, 

    appendHtml: function(collectionView, itemView) { 
     collectionView.$("tbody").append(itemView.el); 
    } 
}); 

템플릿 간단한 물론이다

<script id="grid-template" type="text/template"> 
    <thead>   
     <tr> 
      <th data-sortby="username">Username</th> 
      <th data-sortby="fullname">Full Name</th> 
     </tr> 
    </thead> 
    <tbody></tbody> 
</script> 

로 변성 데릭 원래 데모 바이올린 포크 문제는 여기에 나와 있습니다. http://jsfiddle.net/ccamarat/9stvM/14/

나는 약간 구불 구불 렀다. 제 질문은 좀비보기가 생겼습니다. 이것은 jQuery/Backbone/Underscore 버그입니까? 아니면이 모든 잘못에 대해 간단히 말합니까?

** 수정 ** 다음은 두 요소의 다른 상위 계층 구조를 보여주는 콘솔 출력입니다 :

console.log(target, targetb): 
    [<th data-sortby="username" class="sort asc">Username</th>] [<th data-sortby="username">Username</th>] 

console.log(target.parents(), targetb.parents()): 
    [<tr>…</tr>, <thead>…</thead>] [<tr>…</tr>, <thead>…</thead>, <table>…</table>, <div id="grid">…</div>, <body>…</body>, <html>…</html>] 

console.log(target === targetb): 
    false 
+0

문제/문제에 대해 더 구체적으로 설명 할 수 있습니까?몇 가지 잠재적 인 문제를 매우 자세하게 언급했지만, 좀비보기와 관련하여 세부 사항없이 하나의 매우 짧은 질문 만하십시오. 어떤 문제를 해결하려고합니까? 왜 좀비보기가 있다고 생각하니? 어떤 좀비가 보입니까? –

+0

도 - 최신 버전의 Chrome에서 예를 들어 실행했습니다. 제대로 작동합니다. 당신이 DOM이 업데이트되지 않았다는 코멘트는 ... 실행했을 때 그 시점에서 업데이트되었습니다. 어떤 브라우저/버전을 사용하고 있습니까? –

+0

나보다 한 가지 이상의 문제가있는 것 같으면 나 자신을 설명하는 일이 불쌍한 것입니다. 유일한 문제는 내가 좀비보기라고 부르는 것입니다. 내가 그것을 부른 이유는 적어도 나의 셋업에서, 첫 번째 중단 점 (event.target을 사용)에서 업데이트 된 요소는 두 번째 요소와 동일한 것이 아니라 * $ el.find ()). 저는 최신 버전의 Chrome을 사용하여 테스트 중이며 두 대의 다른 컴퓨터에서 두 번 복제 할 수있었습니다. –

답변

2

나는 좀비보기의 증거를 볼 수 없습니다.

코드 포크를 만들고보기 인스턴스를 확인하기 위해 추가 로깅을했는데 좀비가 보이지 않습니다. 매번 동일한 GridView 인스턴스가 사용됩니다. 그리고 어린이보기는 정렬 될 때마다 올바르게 닫힙니다.

http://jsfiddle.net/derickbailey/hadbf/4/

이 문제는 사용자의 보는이 가능성이 target = $(e.target)targetb = this.$(...)의 사용에 의해 발생합니다. 이것들은 매우 다른 두 개의 문장으로, DOM 요소에 대한 두 가지 다른 소스에서 작동합니다.

target = $(e.target)의 첫 번째 사용은 DOM에서 직접 실행됩니다. 클릭 한 대상에 대해 선택기를 실행하고 있습니다.이 선택기는 jQuery 선택기 개체에서 해당 DOM 요소를 래핑하는 것입니다.

targetB = this.$(...)의 두 번째 용도는 백본보기의 $el을 사용하여 찾기 : this.$el.find("...")을 수행하여보기의 EL에 따라 결과를 반환합니다. 뷰의 $ eL에는 DOM의 일부인 요소가 포함됩니다. 그러나 $ el은 e 이벤트와 같은 대상이 아니므로 target === targetb이 참이 될 것입니다.

... 내가이 문제를 완전히 오해하지 않는 한 (이 시점에서 매우 가능성이있는 것처럼 보이지만) 여기에 문제가 있다고 생각하지 않습니다.

+0

당신의 피들 (Fiddle)은'sort()'가 호출 될 때 무슨 일이 일어나는지 생각해 봤습니다. 기본 컬렉션이 변경되어 모든 서브 뷰를 닫을 수 있습니다. 그러나 헤더 행을 다시 설정할 필요는 없었지만 정확히 어떻게되는지 알 수 있습니다. 'render()'작업은 'renderModel()'을 호출하기 때문에'sort()'는'event.target'라고 불리는 이후 더 이상 DOM의 요소를 가리키지 않습니다. 템플릿에서 뷰를 재생성하고'event.target '과정에서. –

+0

그래서 좀비보기가 아닌 고아 참조를 만들었습니다. 이 문제를 해결하려면 합성보기가 아닌 CollectionView에서 상속하고 initialize() 함수를 재정의하고 템플릿을 수동으로 읽는 방법으로 해결할 수 있습니다. 시간 내 주셔서 감사합니다. –

+0

이제는 CompositeView가 CollectionView에서 확장되고 CollectionView에 콜렉션이 재설정 될 때 .render 메서드를 호출하여 다시 렌더링되는 이벤트 처리기가 내장되어 있기 때문에 발생합니다. 컬렉션을 정렬하면 컬렉션이 다시 설정되므로 전체 컴포지트 뷰가 다시 렌더링됩니다. 복합 뷰의 initialEvents 메소드를 오버라이드하여 해당 동작을 변경할 수 있습니다. http://derickbailey.github.com/backbone.marionette/docs/backbone.marionette.html#section-21 링크는 CollectionView에 있지만 그냥 추가하십시오. CompositeView를 오버라이드 (override)하는 메소드. –