可以在backbone.js中将子视图附加到网格中一次

Possible to append subviews once to grid in backbone.js?

本文关键字:网格 一次 视图 backbone js      更新时间:2023-09-26

我正在通过服务onReady加载JSON数据(对象数组),并希望在网格中显示这些数据。我用一个视图表示每一行。

        render: function(){
            var self = this;
            (self.collection.models).forEach( function(model){
                var rowView = new RowView({model: model});
                self.$el.append(rowView.render().el);
            });                
        }

是否可以构建子视图并将它们一次推送到DOM,而不是一乘一?浏览器是否回流&每次追加都要重新绘制?

我见过人们添加子视图/子视图的所有方法,但都没有解决问题(频繁的DOM访问?),因为这就是构建主干网的方式?

是的,这是可以做到的。使用jQuery生成一个html元素(使用视图的tagName定义和attributes等等),然后将所有内容附加到该元素。完成后,将当前的this.$el换成新的:

render: function(){
  // create in memory element
  var $el = $(this.tagName);
  // also get the `className`, `id`, `attributes` if you need them
  // append everything to the in-memory element
  this.collection.each(function(model){
    var rowView = new RowView({model: model});
    $el.append(rowView.render().el);
  });
  // replace the old view element with the new one, in the DOM
  this.$el.replaceWith($el);
  // reset the view instance to work with the new $el
  this.setElement($el);
}

这样就可以了。

当然,你会在屏幕上看到一点闪烁,这取决于浏览器的速度和变化的大小。但这应该会让你走上做你想做的事的道路。

有关replaceWith的详细信息:http://api.jquery.com/replaceWith/

我认为有一个比@Derick的答案更简单的解决方案:

render : function () {
  var children = [];
  this.collection.forEach( function( model ) {
    var rowView = new RowView( { model : model } );
    children.push( rowView.render().el );
  } );

  this.$el.empty().append( children );

  return this;
}

http://jsfiddle.net/tXnTk/

在@Derick的回答中对代码的评论(我的评论标记为"[JMM]:"):

render: function(){
  // [JMM]: You should already have this.el / this.$el, so there 
  // [JMM]: should be no need to mess with this.tagName, className, 
  // [JMM]: id, etc. Just store the child views in an array.
  // create in memory element
  var $el = $(this.tagName);
  // also get the `className`, `id`, `attributes` if you need them
  // append everything to the in-memory element
  this.collection.each(function(model){
    var rowView = new RowView({model: model});
    $el.append(rowView.render().el);
  });

  // [JMM]: Using replaceWith will wipe out event listener
  // [JMM]: registrations and other data associated with the
  // [JMM]: DOM element. That's why it's necessary to call
  // [JMM]: setElement() afterward. Since you already have
  // [JMM]: the DOM element and you just want to change the
  // [JMM]: content you might as well just empty it out and
  // [JMM]: append the new children.
  // replace the old view element with the new one, in the DOM
  this.$el.replaceWith($el);
  // reset the view instance to work with the new $el
  this.setElement($el);
}