(重新)呈现更改事件处理程序中的 Backbone 视图不起作用

(Re)rendering Backbone view in change event handler does not work

我有两个表单元素,都通过 backbone.stickit 双向数据绑定。 第二个表单元素 (#input) 只是装饰品 - 用于显示它确实有效。

我的想法是,每次下拉菜单中的选项(#select)更改时,我的视图都会(重新)呈现。

我试图通过捕获#select 的 'changed' 事件并调用 this.render() 来(重新)渲染视图来实现这一点。

显然这不起作用。 selected 选项没有保存回模型中,我不明白为什么。

我不是在寻找解决方案,而是解释,为什么以下代码不起作用。解决方案(如:对我有用)是 fiddle 的一部分 - 已注释掉。

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/

从您的 change #select 事件处理程序中调用 this.render() 不起作用的原因是因为您破坏了 Backbone.stickit 为您提供的双向数据绑定。流程如下所示:

  • 用户更改了“#select”的值。
  • 您的 change #select 处理程序触发并调用 this.render()
  • render 使用没有 selected option.
  • 的新 select 菜单重新填充 #ctr
  • Backbone.stickit 响应 #select 的变化。
  • Backbone.stickit 尝试获取 #select 的值,但由于它不包含 selected option,因此值为 undefined.
  • Backbone.sticket 将 modelselect 属性设置为 undefined

如果您将 this.render() 调用移动到 modelchange:select 处理程序中,它会起作用的原因是 Backbone.stickit 能够正确更新模型而无需DOM 在它获得机会之前改变了。