2010-12-27 5 views
3

이것은 Backbone.js를 사용하기위한 첫 번째 시도이므로 메뉴 항목이있는 레스토랑 메뉴를 시뮬레이트하는 간단한 테스트 응용 프로그램을 만들기로 결정했습니다. 나는 this cool blog post from andyet.net과 함께 따라 갔다.Backbone.js | 나중에 검색 할 뷰의 요소를 저장하려면 어떻게해야합니까?

모델을 컬렉션에 추가 할 때 문제가 있습니다. 뷰를 업데이트해야하는 컬렉션의 add 이벤트에 뷰 메서드를 바인딩했습니다. 가능한 한 많은 관련성이없는 코드가 제거 된 코드가 있습니다.

(참고 : 나는 간결하게하기 위해 로컬 범위 var 선언과 폐쇄 등을 제거 다음은 여전히 ​​조금 긴, 내가 그 짜증나는 건 알지만 그것은 매우 간단하고 이해하기 쉬워야한다.)

MenuItem = Backbone.Model.extend({ 
    // initialize functions removed for brevity 
}); 
Menu = Backbone.Model.extend({ 
    // initialize functions removed for brevity 
    // MenuSelection property is defined here. 
}); 
MenuSelection = Backbone.Collection.extend({ model: MenuItem }); 
MenuItemView = Backbone.View.extend({ 
    // render template 
}); 

/** 
* This is unaltered from the code. The error occurs here. 
*/ 
RestaurantAppView = Backbone.View.extend({ 
    addMenuItem : function (MenuItem) { 
     var view = new MenuItemView({ model : MenuItem }); 
     this.menuList.append(view.render().el); 
     // ERROR occurs here. error: "this.menuList is undefined" 
    }, 
    initialize : function() { 
     this.model.MenuSelection.bind('add', this.addMenuItem); 
    }, 
    render : function() { 
     $(this.el).html(ich.app(this.model.toJSON())); 
     this.menuList = this.$('#menuList'); // IT IS DEFINED HERE 
     return this; 
    } 
}); 

/** 
* Everything after this I left in just-in-case you need to see it. 
*/ 
RestaurantAppController = { 
    init : function (spec) { 
     this.config = { connect : true }; 
     _.extend(this.config, spec); 
     this.model = new Menu({ 
      name : this.config.name, 
     }); 
     this.view = new RestaurantAppView({ model : this.model }); 
     return this; 
    } 
}; 
$(function() { 
    // simulating ajax JSON response. 
    var json = { 
     Menu : { 
      name : 'Appetizers', 
      MenuItem : [ 
       { 
        name : 'toast', 
        description : 'very taosty', 
        price : '$20.00' 
       }, 
       { 
        name : 'jam', 
        description : 'very jammy', 
        price : '$10.00' 
       }, 
       { 
        name : 'butter', 
        description : 'very buttery', 
        price : '$26.00' 
       } 
      ] 
     } 
    }; 
    window.app = RestaurantAppController.init({ 
     name : json.Menu.name 
    }); 
    $('body').append(app.view.render().el); 
    app.model.MenuSelection.add(json.Menu.MenuItem); 
}); 

나는 문제가있는 부분에 주석을 표시했습니다. Backbone Documentation :

jQuery 또는 Zepto가 페이지에 포함되어있는 경우 각 뷰에는 뷰 요소 내에서 범위가 지정된 쿼리를 실행하는 $ 함수가 있습니다. 내가 렌더링 방법 this.menuList = this.$('#menuList');을 설정하고있어 경우

그럼, 왜 나는 addMenuItem 방법 this.menuList에 액세스 할 수 없습니다? 상단에 링크 된 데모는 exacly this와 같습니다. 또한 나는 그렇게처럼 jQuery를 선택하기위한 this.menuList를 스왑 아웃 경우 :

addMenuItem : function (MenuItem) { 
    var view = new MenuItemView({ model : MenuItem }); 
    $('#menuList').append(view.render().el); 
} 

모든 것이 잘 작동합니다. 그러나 나는 가 실행될 때마다 을 원하고 menulist ID를 다시 선택하려고하지 않습니다. RightWay TM은 렌더링 된 후에 캐시하는 것입니다.

참고 : ICanHaz 템플릿이 충분히 빠르게 돌아 오지 않는 문제가 있다고 생각했지만 this.menuListundefined이 아니라 빈 배열이됩니다.

답변

8

동적 검색 범위가 this 인 자바 스크립트가 1 위를 차지했습니다. this.addMenuItem을 바인딩하지 않고 참조로 만들면 addMenuItem 함수는 this이라는 개념을 잃게됩니다. 이와

this.model.MenuSelection.bind('add', this.addMenuItem); 

:

this.model.MenuSelection.bind('add', _.bind(this.addMenuItem, this)); 

또는 효율적으로 달성됩니다 초기화 함수의 상단에이 줄을 추가하여 코드를 수정하거나이 줄을 대체 할 두 가지 쉬운 방법이 있습니다 같은 것 :

_.bindAll(this, 'addMenuItem'); 
+0

'_.bindAll (this, 'addMenuItem'); '이 트릭을 수행했습니다. underscore.js 문서가 나를 설명해주었습니다. 감사! – Stephen

0

아마도 render 메서드가 호출되기 전에 addMenuItem 메서드가 호출되어 addMenuItem에 menuList 정의가 없습니다.

왜 푸시하지 않습니까? this.menuList = this. $ ('# menuList'); ~ 메서드를 초기화하고 시도 하시겠습니까?

+0

방금 ​​쐈어. 아직 정의되지 않았습니다.블로그 자습서에는 모든 예가 나와있는 순서대로 나열되어 있습니다. – Stephen

관련 문제