1

backbone.stickit を介して双方向データバインドされた 2 つのフォーム要素があります。2 番目のフォーム要素 ( #input ) は単なる装飾です。実際に機能していることを示すためのものです。

アイデアは、ドロップダウン ( #select ) メニュー内のオプションが変更されるたびに、ビューが (再) レンダリングされることです。

#select の「変更された」イベントをキャッチし、 this.render() を呼び出してビューを (再) レンダリングすることで、それを達成しようとしています。

どうやらそれはうまくいきません。選択したオプションがモデルに保存されず、その理由がわかりません。

次のコードが機能しない理由の説明ではなく、解決策を探しているわけではありません。解決策(次のように:私にとってはうまくいく)はフィドルの一部です-コメントアウトされています。

HTML:

<script type="text/template" id="tpl">
  <h1>Hello <%= select %></h1>
  <select id="select">
  </select>
  <p>Select:
    <%= select %>
  </p>
  <hr>
  <input type="text" id="input">
  <p>Input:
    <%= input %>
  </p>
</script>

<div id="ctr"></div>

JavaScript:

Foo = Backbone.Model.extend({
  defaults: {
    select: "",
    input: "",
  }
});
FooView = Backbone.View.extend({
  el: '#ctr',
  template: _.template($('#tpl').html()),
  initialize() {
    this.model.bind('change', function() {
      console.log("model change:");
      console.log(this.model.get('select'));
      console.log(this.model.get('input'));
    }, this);
    //this.model.bind('change:select', function() { this.render(); }, this); // <--------------------- WORKS
  },
  render: function() {
    this.$el.html(this.template(this.model.toJSON()));
    this.stickit();
    return this;
  },
  events: {
    'change #select': function(ev) {
      console.log('change event triggered:');
      console.log(this.model.get('select'));
      console.log(this.model.get('input'));
      this.render(); // <--------------------- DOES NOT WORK - WHY?
    },
    /* 'click #render': function(ev) {
      console.log('render event triggered:');
      console.log(this.model.get('select'));
      console.log(this.model.get('input'));
      this.render();
    } */
  },
  bindings: {
    '#input': 'input',
    '#select': {
      observe: 'select',
      selectOptions: {
        collection: function() {
          return [{
            value: '1',
            label: 'Foo'
          }, {
            value: '2',
            label: 'Bar'
          }, {
            value: '3',
            label: 'Blub'
          }]
        }
      }
    },
  },
});
new FooView({
  model: new Foo()
}).render();

https://jsfiddle.net/r7vL9u07/9/

4

1 に答える 1

1

this.render()イベント ハンドラー内から呼び出しが機能しない理由は、 Backbone.stickitchange #selectが提供する双方向のデータ バインディングを中断しているためです。流れは次のようになります。

  • ユーザーが「#select」の値を変更します。
  • ハンドラchange #selectが起動して を呼び出しますthis.render()
  • render#ctr選択されていない新しい選択メニューが再表示されoptionます。
  • Backbone.stickit は への変更に対応し#selectます。
  • Backbone.stickit は の値を取得しようとしますが#select、選択されたものが含まれていないためoption、値はundefinedです。
  • Backbone.sticket はmodelselect属性を に設定しますundefined

this.render()呼び出しをmodelのハンドラー内に移動すると機能する理由change:selectは、Backbone.stickit がチャンスを得る前に DOM を変更せずにモデルを正しく更新できるためです。

于 2016-04-03T05:58:01.757 に答える