【问题标题】:Backbone.js fires render twice on collection addBackbone.js 在集合添加时触发渲染两次
【发布时间】:2012-04-19 12:38:35
【问题描述】:

在学习 Backbone.js 的同时,我正在使用 Todos 示例应用程序 bundled with the latest version of Backbone (0.9.2)。我的问题是,为什么应用程序设计为在向 Todos 集合添加模型时触发两次渲染事件?

如果我将这一行放在 TodoView 的渲染函数中:

// Re-render the titles of the todo item.
render: function() {
  console.log("Rendering!");
  this.$el.html(this.template(this.model.toJSON()));

然后是“渲染!”在控制台中出现两次。我理解这是因为视图将模型的更改事件绑定到视图的渲染:

initialize: function() {
  this.model.bind('change', this.render, this);

并且在addOne中调用了render,绑定了Todos的add事件:

addOne: function(todo) {
  var view = new TodoView({model: todo});
  this.$("#todo-list").append(view.render().el);
},

但是这种双渲染设计是标准做法吗?看起来视图应该在创建(或进入 DOM)时呈现,然后在底层模型发生变化时再次呈现。在这种情况下,什么都没有改变,但是渲染被调用了两次。

再说一次,我只是在学习 Backbone,所以我可能有一个基本的误解导致我的困惑。

【问题讨论】:

    标签: javascript backbone.js


    【解决方案1】:

    嗯,看了一下。发生这种情况是对的,不,这不是标准做法。 原因有点模糊,请耐心等待;)

    待办事项应用正在使用主干本地存储。当您尝试在应用中添加新项目时,它会调用:

    createOnEnter: function(e) {
      if (e.keyCode != 13) return;
      if (!this.input.val()) return;
    
      Todos.create({title: this.input.val()});
      this.input.val('');
    },
    

    注意Todos.create。通常create 会将模型添加到集合中并将其保存在服务器上。 add 事件将因此被触发。尽管主干本地存储在create 上执行以下操作,但它发生了:

    create: function(model) {
      if (!model.id) model.set(model.idAttribute, guid());
      this.data[model.id] = model;
      this.save();
      return model;
    },
    

    注意model.set 给模型一个ID。这就是触发(第二个)change 事件的原因。

    您可以通过将 create 更改为 do 来阻止这种情况发生:

    if (!model.id) model.id = guid();

    【讨论】:

    • 很好!.. 你也可以使用{silent: true} 来避免触发事件。
    • 你是对的,这就是改变事件被触发的原因。但是,以您建议的方式更改代码会停止事件,但也会破坏功能(我无法再删除项目)。显然,这对于回答我的问题并不重要,但以防万一将来有人读到这个,我想指出这一点。
    • 删除项目永久即。删除后,如果我刷新它们仍然存在。
    • 删除不会受到影响,除非您也更改了其他内容或存在其他错误。我猜骨干本地存储可能很快需要好好清理一下;)
    【解决方案2】:

    重新渲染不应该发生。

    尝试调试一点。尝试将 change 事件绑定到 wrapper 方法,例如:

    initialize: function(){
      this.model.bind( "change", this.renderWrapper, this );
    }, 
    
    renderWrapper: function(){
      console.log( "in the renderWrapper" );
      this.render();
    }
    

    确保第二个render() 是为更改事件绑定 而不是出于其他原因。

    【讨论】:

    • 你是对的。我应该在我的问题中指出,我最初通过将console.log('Change!') 代替this.render() 来缩小范围。因此,我确信更改事件正在触发。
    猜你喜欢
    • 2011-12-19
    • 1970-01-01
    • 2016-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-19
    • 2013-09-19
    相关资源
    最近更新 更多