2016-06-27 8 views
0

을 제거하지 undelegateEvents :Backbone.js : 다음 코드에서 이벤트

HTML

<div id="myView"> 
    <button id="test_button"> 
    Test Button 
    </button> 
    <ul id="output"></ul> 
</div> 

자바 스크립트

var myView = Backbone.View.extend({ 

    initialize: function() { 
     // why doesn't this remove the previously delegated events? 
     this.undelegateEvents(); 

     this.delegateEvents({ 
      'click #test_button': 'buttonClicked' 
     }); 
    }, 

    // this event fires twice for one button click  
    buttonClicked: function() { 
     $("#output").append('<li>Button was clicked</li>'); 
    } 
}); 

$(document).ready(function(){ 
    new myView({el: "#myView"});  

    // instantiate view again 
    new myView({el: "#myView"}); 
}); 

this.undelegateEvents(); 
을한다

은 Backbone View의 initialize() 메서드에서 이전에 위임 된 이벤트를 이전에 View의 인스턴스화에서 제거하지 않습니까? 위의 코드의

JSFiddle 예제 : https://jsfiddle.net/billb123/o43zruea/28/

+0

보기를 두 번 초기화하여 수행하려는 작업을 이해하지 못합니다. 실행중인 undelegateEvents를 보려면 buttonClicked 안에 append 뒤 이동하고 View를 한 번 인스턴스화합니다. 클릭은 한 번만 실행되고 이벤트 바인딩은 제거됩니다. – bdc

+0

@bdc - 백본 경로에서 인스턴스를 생성하여 뷰를 전환하는 백본 응용 프로그램이 있습니다. 그러나이 뷰에 대한 경로가 뷰를 인스턴스화 한 횟수에 따라 여러 번 발생하는 특정 뷰에서 위임 된 이벤트가 발생합니다 (즉, 사용자가 페이지를 다시로드하지 않고 뷰간에 앞뒤로 이동 함). 나는 위임 된 이벤트를 다시 위임하기 전에 뷰에 대한 위임 된 이벤트를 단순히 제거하여이 문제를 해결할 수 있다고 생각했습니다. 게다가, 필자는 나의 예제가 무엇을 하는지를 알고 싶다 - 나는 undelegateEvents가 정확하게 그것을 할 것이라고 생각할 것이다. – Bill

+2

경로를 전환하기 전에 undelegateEvents를 호출하면 initialize()가 작동하지 않습니다. 내부 초기화가 작동하지 않는 이유는 뷰의 별도 인스턴스 두 개를 인스턴스화하기 때문입니다. 두 번째 인스턴스는 첫 번째 인스턴스의 이벤트에 바인딩되지 않습니다. 백본 소스 : this. $ el.off ('. delegateEvents'+ this.cid). this.cid는 DOM 요소가 같더라도 인스턴스화하는 각 뷰에 대해 고유합니다. – bdc

답변

3

나는 소리하지 않으려 고하지만, 기존의 요소 뷰를 결합하는 시도를 중단하시기 바랍니다 것입니다. 보기가 자신의 el을 만들고 소유 한 다음 view.remove()으로 전화하여 교체하기 전에 종료하십시오. 이 간단한 변경은 이런 방식으로하지 않으면 항상 두 번 (그리고 두 번) 생각해야하는 뷰 이벤트에서 많은 문제를 해결합니다.

<script id="t" type="text/x-underscore"> 
    <div id="myView"> 
    <button id="test_button"> 
     Test Button 
    </button> 
    </div> 
</script> 
<div id="container"> 
</div> 
<ul id="output"> <!-- This is outside the container because we're going to empty and refill it --> 
</ul> 

를 그리고 자바 스크립트는 다음과 같이 보일 것이다 : 당신의 경우

,이 같은 HTML이있을 것이다 관심의

var myView = Backbone.View.extend({ 
    events: { 
    'click #test_button': 'buttonClicked' 
    }, 
    render: function() { 
    this.$el.html($('#t').html()); 
    return this; 
    }, 
    buttonClicked: function() { 
    $("#output").append('<li>Button was clicked</li>'); 
    } 
}); 

$(document).ready(function(){ 
    var v = new myView(); 
    $('#container').append(v.render().el); 

    v.remove(); // <----------------- Clean things up before adding a new one 

    v = new myView(); 
    $('#container').append(v.render().el); 
}); 

포인트 :

  1. 만들기 보기를 렌더링 한 다음 페이지에 놓습니다.
  2. 완료되면보기에서 remove으로 전화하십시오.
  3. 보기가 컨테이너 내부로 들어갑니다. 호출자는 컨테이너를 소유하고 뷰는 el을 소유합니다.
  4. 어디서나 delegateEvents 또는 undelegateEvents 전화가 없습니다. 이들의 존재는 거의 항상 애플리케이션 IMO의 구조적 문제를 지적합니다.
  5. 각보기는 자체 포함되어 있습니다. 바깥 세상은보기 안의 아무 것도 재생하지 않으며보기는 손을 자체로 유지합니다.

는 바이올린 업데이트 : https://jsfiddle.net/bp8fqdgm/


을하지만 왜 아무것도 할 undelegateEvents을 시도하지 않았다? undelegateEvents looks like this :

undelegateEvents: function() { 
    if (this.$el) this.$el.off('.delegateEvents' + this.cid); 
    return this; 
}, 

cid 뷰 인스턴스 당 고유 각각의 뷰 인스턴스가 이벤트 delegateEvents 바인딩에 대한 고유 네임 스페이스를 사용합니다.

this.undelegateEvents(); 
this.delegateEvents(); 

말하고있다 :

  1. 뷰의이 인스턴스가 바인드 한 이벤트를 제거 즉,이는 것을 의미한다. 이 이벤트는 이 각보기 인스턴스마다 고유 한 '.delegateEvents' + this.cid 네임 스페이스에 있습니다.
  2. 뷰의이 인스턴스가 정의한 이벤트 (또는 delegateEvents 호출의 이벤트)를 바인딩합니다. 이러한 이벤트는 '.delegateEvents' + this.cid 네임 스페이스를 사용하여 연결됩니다.

그래서 undelegateEvents 호출은 이벤트가 아니라 그들 모두의보기 예를이 제거 추가 만 특정 이벤트 바인딩을 제거하고 있습니다.

this.undelegateEvents() 전화가 잘못된 장소에 있고 잘못된 시간에 호출 되었기 때문에 실제로 아무것도 수행하지 못합니다.

var v = new myView({el: "#myView"});  
v.undelegateEvents(); 
new myView({el: "#myView"}); 

는 다음이 적재 적소에 일어날 다음 new View 호출자는 undelegateEvents 전화를 한 경우. 물론 이는 라우터가 현재보기를 추적하여 적절한 시간에 currentView.undelegateEvents()이 될 수 있어야 함을 의미합니다. 그러나 만약 당신이 그 일을한다면 당신은 (IMO) 내가 대답의 맨 위에서 설명한 접근 방식을 취하는 것이 나을 것입니다.

+0

@TJ하지만 실제로 모든보기 이벤트 문제를 해결하는 간단한 트릭입니다. :) –