2

ここで些細なことを見逃している可能性がありますが、ドキュメントとコードの両方がそうすべきだと言っていますが、 setElement はイベントを再バインドしていないようです。

できるだけ少ないコードで問題を再現しようとしましたが、それでもかなりの量なので、Gist に投稿しました。

https://gist.github.com/gooli/baecc277d864e28eb2c7

チェックボックスの1つをクリックすると、コンソールに「選択済み」と表示されます。しかし、もう一度クリックすると、入力はイベントにバインドされなくなります。

<tr>テンプレートに内部要素だけでなく要素を含めたいので、これを行ってい<td>ます。

<tr>要素を削除し、ビューで使用し、レンダリングtagName: 'tr'に共通の式を使用すると、問題なく動作します。this.$el.html(...)

私は何が欠けていますか?

4

2 に答える 2

2

jakee の回答に基づいて、内部のテンプレート ロジックの再実装を必要としないさらに優れたソリューションを思いつきましたrender

window.DayView = Backbone.View.extend({
    template: Handlebars.compile($('#day-template').html()),
    events: {
        'click .select input': 'select'
    },
    initialize: function () {
        this.model.bind('change', this.render, this);
        this.setElement(this.template(this.model.toJSON()));
    },
    render: function() {
        console.log('render');
        this.$el.html($(this.template(this.model.toJSON())).html());
        return this;
    },
    select: function (event) {
        console.log('selected');
        this.model.set({selected:$(event.target).is(':checked')});
    }
});

このinitializeメソッドは、テンプレート全体を使用して要素を作成します。このrenderメソッドは、テンプレートの内部 html のみを使用して新しい値をレンダリングします。

これはきれいに見え、に依存せずにテンプレートでビューの HTML をすべて定義することができますtagName。私は幸せなキャンパーです。

于 2013-06-17T13:52:23.263 に答える
1

あなたのアプローチは、いくつかの理由で問題があります。

this.model.each(function(day) {
  that.$el.append(new DayView({model:day}).render().$el);
});

DayViewここで、要素を に追加しますDayListView$el各ビューの を親ビューの に追加します$elこれは、子要素に固定ラッパー要素がある場合の標準です。tagNameこれは、属性を定義する場合です。しかし、ビューの要素を頻繁に再割り当てする場合、これは問題になります。

  1. ItemView 要素を親に追加します
  2. 選択をクリックします
  3. undelegateEventsItemView に対して呼び出されます
  4. ItemView の新しいテンプレートが取り込ま$elれますel
  5. delegateEventsItemView に対して呼び出されます

今、あなたが抱えている問題の原因は次のとおりです。

  1. 古い ItemView の内容は親ビューから削除されません
  2. 新しい ItemView コンテンツは親ビューに追加されません
  3. イベントは、DOM にない要素に委譲されます。

あなたの問題に対する私の解決策は次のとおりです。

window.DayView = Backbone.View.extend({
  template: Handlebars.compile($('#day-template').html()),
  events: {
    'click .select input': 'select'
  },
  initialize: function () {
    this.model.bind('change', this.render, this);
    this.setElement(this.template(this.model.toJSON()));
  },
  render: function() {
    this.$el.find('.name').text(this.model.get('name'));
    this.$el.find('.select input').attr('checked', this.model.get('selected'));
    return this;
  },
  select: function (event) {
    this.model.set({selected:$(event.target).is(':checked')});
  }
});

このようにして、チェックボックスがクリックされるたびにビューの要素を置き換える必要はありません。現在、このソリューションは最適とはほど遠い可能性がありますが、正しい方向を示しているはずです。

お役に立てれば!

于 2013-06-17T12:58:55.180 に答える