如何在使用不断更新的JSON时正确更新Marionette上的子视图

时间:2013-12-05 14:04:17

标签: backbone.js marionette

我有一个使用Marionette构建的单页应用程序,其主视图包含子视图列表。

保存所有应用程序数据的JSON不断更新。我试图将区域显示代码分开,以便它只运行一次而不是每次渲染。

现在,即使JSON是静态数据,也会在每个超时循环上触发render事件,因此change事件不应该调用render。怎么了?我假设它与.set有关但是有没有其他方法可以将数组变量的响应加载到子视图集合,因为fetch只允许url属性并且不接受数组变量?

此示例是应用程序代码的极简化版本,专注于此特定问题。

控制器:

var Controller = {

   showMainView: function(id){

     // create model and fetch data on startup
     var mainElement = new mainElement();
     var mainElementFetched = mainElement.fetch({url: 'http://json.json'});

     // fetch done, create view, show view in region, setTimeout
     mainElementFetched.done(function(data){

       var mainElementView = mainElementView({model:mainElement});

       App.mainRegion.show(mainElementView);

       setTimeout(updateJSON, 5000);

     }

     // timeOut loop to check for JSON changes
     var updateJSON = function(){

       mainElement.fetch({url: 'http://json.json'});
       App.timeOut = setTimeout(updateJSON, 5000);

     }

   }
}

MainElement模型:

MainElement = Backbone.Model.extend({
  parse : function(response){
    // parsing code
    return response;
  }
});

MainElementView(布局):

MainElementView = Backbone.Marionette.Layout.extend({
  template: "#main-template",
  initialize:function(){

     //create collection for subelements
     this.subElementCollection = new SubElementCollection();

     //listen to change event, and fire callback only when change in model is detected
     this.model.on('change', this.render, this);

  },
  regions:{
    subsection : ".subsection"
  },
  onShow: function(){
    // show subelements in subsection region when mainelementview is shown on screen, but not show on every render
    this.subsection.show(new SubElementCompositeView({collection:this.subElementCollection}))
  },
  onRender : function(){
    var response = this.model.response;
    // get subelements when change event fires and parse the response
    this.subElementCollection.set(response,{parse:true});
  }

});

SubElement Model,Collection,ItemView,CompositeView:

SubElement = Backbone.Model.extend({});

SubElementCollection = Backbone.Collection.extend({

  model:SubElement,
  comparator : function(model){
    var price = model.get('price');
    return -(price);
  },
  parse:function(response){

    // parsing code to get data to models from differents parts of JSON

    return response;

  }

});

SubElementItemView = Backbone.Marionette.ItemView.extend({
  template: "#subelement-template",
  tagName: "tr"


});

SubElementCompositeView = Backbone.Marionette.CompositeView.extend({
  template: "#subelements-template",
  tagName : "table",
  itemView:SubElementItemView,
  itemViewContainer : "tbody",
  initialize: function(){
    this.collection.on('change', this.render, this);
  },
  appendHtml : function(collectionView,itemView,index){

    // SORTING CODE

  },
  onRender:function(collectionView,itemView,index){

    // ADD IRRELEVANT EXTERNAL STUFF TO TEMPLATE AFTER RENDER

  }

});

1 个答案:

答案 0 :(得分:0)

Check out the documentation。它说:

A "change" event will be triggered if the server's state differs from the current attributes.

在绑定到模型更改事件MainElementView的{​​{1}}中,您实际上是在每次模型更改时都说,请调用渲染。

如果由于更改量的原因,重新绘制整个视图的速度太慢。为什么不让渲染更精细?例如,您可以侦听特定的更改事件,只需更改需要更改的DOM元素:

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

设置它是更多的工作,但是你可以通过将模型属性名称与DOM元素名称或其他东西相匹配来使它更聪明。