2

DOMドキュメントフラグメントを使用して大きなテーブルをレンダリングするようにBackboneアプリを変更しました。これにより、行が多い場合にパフォーマンスが大幅に向上します。

残念ながら、これはイベント処理を壊すように思われるため、各行のビューはクリックイベントを受け取らなくなります。これを示すために最小限の例を作成しました。

これを修正するにはどうすればよいですか?

// Javascript
$(window).load(function(){

  var Item = Backbone.Model.extend();

  var Items = Backbone.Collection.extend({
      model: Item,
      count: 5,
      initialize: function() {
        for(i=0; i<this.count; i++){
          this.add(new Item({text: i}));
        }
      }
  });

  var ItemView = Backbone.View.extend({
      tagName: 'tr',

      initialize: function(item) {
        this.item = item;
      },

      render: function() {
        this.$el.append('<td class="item">' + this.item.get('text') + '</td>');
        return this;
      },

      events: function() {
        return { "click .item": function() {
            console.log('handling click on item '+this.item.get('text'));
          }
        };
      }

  });

  var TableBodyView = Backbone.View.extend({
      tagName: 'tbody',

      render: function() {
          if(this.options.useFragment){
              this.renderWithFragment();
          } else {
               this.renderWithoutFragment();
          }
        return this;
      },

      renderWithFragment: function() {
          var fragment = document.createDocumentFragment();
          this.collection.each(function(item){
            fragment.appendChild((new ItemView(item)).render().el);
          });
          this.$el.append(fragment.cloneNode(true));
      },

      renderWithoutFragment: function() {
          self = this;
          this.collection.each(function(item){
              self.$el.append((new ItemView(item)).render().el);
          });
      }
  });

var items = new Items();
$('#t1').append((new TableBodyView({collection: items, useFragment: false})).render().el);
$('#t2').append((new TableBodyView({collection: items, useFragment: true})).render().el);
});

// HTML
<table id="t1" />
<table id="t2" />

// CSS
table { float: left; margin: 10px; padding: 5px; }
table#t1 { background: green; }
table#t2 { background: red; }
4

1 に答える 1

4

問題は、cloneNodeイベントハンドラーを明示的にコピーしないことです。

ノードのクローンを作成すると、そのすべての属性とその値がコピーされますが、イベントリスナーはコピーされません。

したがって、これを行うと:

this.$el.append(fragment.cloneNode(true));
// No more events -------^ 

delegateビューにアタッチされているバックボーンが失われel、すべてのイベント処理が失われます。のクローンを作成しelてイベントを保持する場合はwithDataAndEvents、jQueryでフラグを使用できcloneます。

.clone([withDataAndEvents] [、deepWithDataAndEvents])

withDataAndEventsイベントハンドラーとデータを要素と一緒にコピーする必要があるかどうかを示すブール値。デフォルト値はですfalse

deepWithDataAndEvents複製された要素のすべての子のイベントハンドラーとデータをコピーする必要があるかどうかを示すブール値。デフォルトでは、その値は最初の引数の値(デフォルトはfalse)と一致します。

したがって、代わりに次のように実行できるはずです。

this.$el.append($(fragment).clone(true));

デモ(コンソールを開いてください):http://jsfiddle.net/ambiguous/M6SvH/

于 2012-11-18T00:06:44.417 に答える