2012-02-03 3 views
5

나는 완전히 여기에 뭔가를 누락 될 수 있습니다,하지만 난 다음이 : 콜렉션을 생성 한 후 backbone.js를 사용하여 함수를 실행 하시겠습니까?

  • 모델이 하나 (또는 ​​그 이상)가 (모든 JSON 하나의 URL에서로드)

    • '모든'데이터를 캡슐화하는 모델 그것은 건설
    • 나는 데이터가 초기화 될 때 컬렉션 실행하려면 내 질문은 합성 컬렉션에 관한

    로드 일부 코드를 가지고 데이터로 인스턴스화됩니다 컬렉션. Collection의 범위 밖에서이 작업을 수행 할 수 있지만 캡슐화하는 것이 좋습니다 (그렇지 않으면 이니셜 라이저가있는 '클래스'로 만드는 것이 무엇인지).

    1. 나는 내가 initialize() 기능에 해당 코드를 넣을 수 있다고 생각하지만, 그 모델이 채워지기 전에, 내가 컬렉션을 구성하는 모델 (this.models이 비어)에 액세스 할 수 없습니다 실행됩니다.

    2. 그런 다음 이벤트에 바인딩 할 수 있다고 생각했지만 초기화 후에 이벤트가 트리거되지 않았습니다. 그들은 자신의 종점에서 fetch 컬렉션을로드하는 경우 될 것입니다,하지만 나는 그것을하지, 내가 기존 데이터에서 컬렉션을 초기화 해요.

    내 질문 : (즉 this.models가 비어 있지 않은)가 데이터로 초기화 후 즉시 컬렉션에서 실행하는 코드를 초기화하는 방법을.

    '외부'코드가 필요없이이를 수행 할 수 있습니까?

    여기에 데모 코드가 있습니다. 더 잘 설명 할 수 있습니다.

    var Everything = Backbone.Model.extend({ 
        url: "/static/data/mydata.json", 
        parse: function(data) 
        { 
         this.set("things", new Things(data.things, {controller: this})); 
        } 
    }); 
    
    var Thing = Backbone.Model.extend({ 
    }); 
    
    var Things = Backbone.Collection.extend({ 
        model: Thing, 
        initialize: function(data, options) 
        { 
         // HERE I want access to this.models. 
         // Unfortunately it has not yet been populated. 
         console.log("initialize"); 
         console.log(this.models); 
         // result: [] 
    
         // And this event never gets triggered either! 
         this.on("all", function(eventType) 
         { 
          console.log("Some kind of event happend!", eventType); 
         }); 
        } 
    }); 
    
    var everything = new Everything(); 
    everything.fetch(); 
    
    // Some manual poking to prove that the demo code above works: 
    
    // Run after everything has happened, to prove collection does get created with data 
    setTimeout(function(){console.log("outside data", everything.get("things").models);}, 1000); 
    // This has the expected result, prints a load of models. 
    
    
    // Prove that the event hander works. 
    setTimeout(function(){console.log("outside trigger", everything.get("things").trigger("change"));}, 1000); 
    // This triggers the event callback. 
    
  • 답변

    7

    은 불행하게도 당신을 위해 수집은 제대로 처음 초기화 및 모델 이벤트가 트리거되지 않음을 의미 silent: true 플래그를 사용하여 재설정 된 후에 만 ​​데이터로 설정됩니다.

    정말 사용하고 싶다면 setTimeout (..., 0) 또는 밑줄 defer 메서드를 사용하여 다음 브라우저 이벤트 루프로 원하는 것을 실행을 지연 시켜서 약간의 속임수를 쓸 수 있습니다.

    initialize: function(data, options) { 
    
        _.defer(_.bind(this.doSomething, this)); 
    }, 
    
    doSomething: function() { 
    
        // now the models are going to be available 
    } 
    
    +0

    나는 컬렉션의 생성을 동 기적으로 수행하기를 바랬다. (예를 들어,'Everything.parse'의 다음 줄에서 사용할 수있다.) 분명히 연기하면 안된다. 나는 수집 물에서 논리를 옮겨야 할 수도 있습니다. Backbone.js에 대한 변경 요청 (아마도 ... – Joe

    +0

    ) 'defer'를 사용하면 webCGM에 EventListener를 설치하려는 경우 이상적입니다. WebCGM 다이어그램은 독립적 인 객체로로드되며, 멍청한 그림으로 생명을 시작합니다. 이벤트 전송을 시작하도록 명시 적으로 알려야합니다. 그런 다음 이벤트를 백본 인프라로 다시 파이프 할 수 있습니다. 나는 같은 기술이 다른 플러그인 (SVG/PDF 등)과 상호 작용하는 데 사용될 수 있다고 생각합니다. 대부분이 broswer에서 잘 작동하지 않습니다. –

    0

    이 질문은 오래된 질문입니다. 비슷한 문제가있어서이 솔루션을 만드는 데 도움이되었습니다.

    집합 함수를 확장하면 컬렉션 데이터가 실제 모델로 변환 된시기를 알 수 있습니다. (집합은 .add 및 .reset에서 호출됩니다. 이는 가져 오기 옵션에서 reset 또는 set과 상관없이 가져 오기에서 Collection 클래스를 인스턴스화하는 핵심 함수 중에 호출된다는 것을 의미합니다. 백본 주석 소스로 들어가고 함수 흐름을 따르십시오 여기에서 도왔다)

    이렇게하면 실행 흐름을 해킹하지 않고 알림을받는시기와 방법을 제어 할 수있다.

    var MyCollection = Backbone.Collection.extend({ 
        url: "http://private-a2993-test958.apiary-mock.com/notes", 
        initialize: function() { 
        this.listenToOnce(this, 'set', this.onInitialized) 
        }, 
    
        onInitialized:function(){ 
        console.log("collection models have been initialized:",this.models) 
        }, 
    
        set: function(models,options){ 
        Backbone.Collection.prototype.set.call(this, models, options); 
        this.trigger("set"); 
        } 
    }) 
    
    //Works with Fetch! 
    var fetchCollection= new MyCollection() 
    fetchCollection.fetch(); 
    
    //Works with initializing data 
    var colData = new MyCollection([ 
         {id:5, name:'five'}, 
         {id:6, name:'six'}, 
         {id:7, name:'seven'}, 
         {id:8, name:'eight'} 
        ]) 
    
    //doesn't trigger the initialized function 
    colData.add(new Backbone.Model({id:9,name:'nine'}; 
    

    참고 : 우리가 .listenToOnce를 사용 해달라고한다면, 우리는 또한 모델뿐만 아니라 컬렉션에 추가되거나 변경 될 때마다 호출 onInitialized을 얻을 것이다.