2012-07-23 24 views
0

我注意到我的視圖的渲染函數被調用了2次。 這裏是我的代碼:backbone.js視圖不會顯示結果,因爲異步獲取,不會呈現

視圖,其獲得的集合:

define([ 
    'jquery', 
    'underscore', 
    'backbone', 
    'mustache', 
    'icanhaz', 
    'views/spots/Spot', 
    'collections/Spots', 
    'text!../../../../templates/spots/spots.mustache!strip', 
], function($, 
      _, 
      Backbone, 
      mustache, 
      ich, 
      SpotView, 
      Spots, 
      SpotsTemplate){ 
    var SpotsView = Backbone.View.extend({ 

    initialize: function(){ 
     var ich = window['ich'], 
      spots = ich.addTemplate('spots',SpotsTemplate); 

      spots = ich['spots']; 

      this.template = spots; 

     _.bindAll(this,'render'); 
     var self = this; 
     this.collection.bind("all", function() { self.render(); }, this); 
     this.collection.fetch(); 
    }, 
    events: { 
     "change": "render" 
    }, 
    render: function(){ 
     window.counter = window.counter +1; 
     console.log('inside render for the ' + window.counter + ' times!'); 

     this.el = this.template(); 

     this.collection.each(function (spot) { 

     $(this.el).append(new SpotView({model:spot}).render().el); 
     }, this); 

     console.log($(this.el).children().length); 

     return this; 
    } 
    }); 
    // Returning instantiated views can be quite useful for having "state" 
    return SpotsView; 
}); 

內app.js的代碼,當我嘗試顯示

var spots = new Spots({model: Spot}); 

    window.counter = 0 + 0; 

    var spots_view = new SpotsView({collection: spots}); 
    $('#spots').html(spots_view.render().el); 

我的輸出是:

inside render for the 1 times! 
1 
inside render for the 2 times! 
6 

雖然玩不同的東西我發現它被稱爲3次甚至。我究竟做錯了什麼?顯然由當時的結果從服務器帶來的渲染功能這一行:

$('#spots').html(spots_view.render().el); 

已通過

非常感謝

回答

2

您的視圖的initialize這樣說:

this.collection.bind("all", function() { self.render(); }, this); 
this.collection.fetch(); 

fetch將重置集合:

當模型數據從服務器返回時,集合將重置。

Resetting the collection將:

[觸發器]一個單一的 「復位」 事件在端

通過結合"all",在收集任何事件將觸發render呼叫。因此,當您明確說出spots_view.render()並且fetch調用從服務器返回某些內容時,您的視圖將會呈現一次。

順便說一句,你有這樣的:

_.bindAll(this,'render'); 

,這樣你就不需要使用selfself.render()或提供上下文參數bind,你可以簡單地這樣說:

_.bindAll(this, 'render'); 
this.collection.bind("all", this.render); 

你也在做這個render

this.el = this.template(); 

,這絕不是一個好主意。如果您需要更改視圖的this.el,則應該使用setElement;這將照顧重新綁定事件並更新this.$el。但是,如果您已將this.el添加到DOM中,那不會對您有所幫助。而不是取代el完全的,你應該把你需要的內部this.el一切:

var $content = $(this.template()); 
this.collection.each(function (spot) { 
    var spot = new SpotView({ model: spot }); 
    $content.append(spot.render().el); 
}); 
this.$el.html($content); 

然後你就可以清空它和響應事件沒有任何問題重新渲染它。

+0

非常感謝您的參與,所以在抓取時最佳做法是什麼?我看到它用於視圖的初始化(這將在2個渲染調用中產生)。 – user1271518 2012-07-24 08:35:12

+0

它也不能解決我的問題,因爲我再次得到2次訪問渲染函數,一次沒有數據,另一次當有,即使從外部控制器(app.js)調用提取。 。你可以看到我從app.js調用:「var spots_view = new SpotsView({collection:spots});」它調用初始化方法並獲取數據,下一行是:「$('#spots')。html(spots_view.render()。el);」應該已經有數據顯示,但沒有 – user1271518 2012-07-24 08:35:51

+0

@ user1271518:爲什麼你的'render'被調用了兩次?讓你的'渲染'足夠聰明,無所謂。 'fetch'的最佳做法是根據您的應用程序和特定情況進行選擇。有時將渲染調用放在一個「成功」回調中是有意義的,有時候可以讓你的渲染使用未提取或提取的模型。 – 2012-07-24 08:54:38