2015-01-21 58 views
0

一種簡單demoBackbone.View.setElement工作意外

this.listenTo(this.model, 'change', this.render); 

然而儘管render方法是:

var PersonListView = Backbone.View.extend({ 
     initialize: function() { 
      this.listenTo(this.collection, 'add', this.addOne); 
      this.listenTo(this.collection, 'reset', this.addAll); 
     }, 
     addOne: function (model) { 
      var subView = new PersonItemView({model: model}); 
      $(this.el).append(subView.render().el); 
     }, 
     addAll: function() { 
      $(this.el).empty(); 
      this.collection.each(this.addOne, this); 
     }, 
     render: function() { 
      this.addAll(); 
      return this; 
     } 
    }); 
    var PersonItemView = Backbone.View.extend({ 
     template: _.template($('#tpl_person_item').html()), 
     initialize: function() { 
      this.listenTo(this.model, 'remove', this.remove); 
      this.listenTo(this.model, 'change', this.render); 
     }, 
     render: function() { 
      console.info("render person:" + this.model.get("name")); 
      var el = $(this.template(this.model.toJSON())); 
      this.setElement(el); 
      return this; 
     } 
    }); 

    var p = new Person({name: 'name1'}); 
    var ps = new PersonList(); 
    ps.add(p); 
    new PersonListView({ 
     el: $("#list"), 
     collection: ps 
    }).render(); 
    setTimeout(function() { 
     p.set("name", "new name") 
    }, 5000); 

如圖所示,我通過change事件模型的綁定到視圖稱爲元素不會更新到頁面。

看來setElement不會將其el添加到dom中。

如何解決這個問題?

回答

0

我有點生疏骨幹,我並不完全滿意這是一個解決方案,但這個工程:改變你的PersonItemView類的樣子:

var PersonItemView = Backbone.View.extend({ 
    template: _.template($('#tpl_person_item').html()), 
    initialize: function() { 
     this.el = null; 
     this.listenTo(this.model, 'remove', this.remove); 
     this.listenTo(this.model, 'change', this.render); 
    }, 
    render: function() { 
     console.info("render person:" + this.model.get("name"), this.el); 
     if (this.el == null) { 
      var el = $(this.template(this.model.toJSON())); 
      this.setElement(el); 
     } 
     else { 
      $(this.el).replaceWith($(this.template(this.model.toJSON()))); 
     } 
     return this; 
    } 
}); 

也許一個更好的解決辦法是爲PersonListView.addOne創建一個空的<li>元素並將其傳遞給構造函數PersonItemView,那麼PersonItemView.render總是可以使用replaceWith

0

當您更改模型時,只執行PersonItemView的呈現。該函數正在改變視圖的EL,但不會根據您的代碼更新DOM。

當你只在集合視圖更新DOM只呈現完整集合時甚至單一的模式

var PersonListView = Backbone.View.extend({ 
     initialize: function() { 
      this.listenTo(this.collection, 'add', this.addOne); 
      this.listenTo(this.collection, 'reset', this.addAll); 
      this.listenTo(this.collection, 'change', this.addAll); 
     }, 

JSBIN

方案2的變化: setElement覆蓋元件的EL,所以你更新不在DOM中的元素。所以不要使用setElement,只需更新相同的el。

var PersonItemView = Backbone.View.extend({ 
     render: function() { 
      console.info("render person:" + this.model.get("name")); 
      this.$el.html(this.template(this.model.toJSON()); 
      return this; 
     } 
    }); 

如果您想使用setElement,請確保您將el再次添加到DOM。這不會發生在您的代碼中。

+0

我試圖避免刷新整個集合視圖一次只有一個項目進行更新。 – hguser 2015-01-21 07:00:24

+0

@hguser已更新 – StateLess 2015-01-21 07:03:31