2012-04-19 12 views
8

私は、Backbone.jsについて学びながら、Todosサンプルアプリケーションbundled with the latest version of Backbone(0.9.2)で作業しています。私の質問は、なぜアプリケーションがTodosコレクションにモデルを追加するときにレンダリングイベントを2回発生させるように設計されているかです。Backbone.jsは、コレクションに2回レンダリングを実行します。

私はTodoViewの機能レンダリング中にこの行を配置する場合: "!レンダリング" すると

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

をコンソールに2回表示されます。私は、ビューは、ビューのレンダリングには、モデルの変更イベントを結合するので、これは理解:

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

とレンダーはaddOneで呼び出され、トドスにバインドされたイベントを追加します。

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

しかしありますこのダブルレンダリングデザインの標準的な練習ですか?ビューが作成時(またはDOMへの入り口)にレンダリングされるように見えるように見えます。この場合、何も変更されていませんが、レンダリングは2回呼び出されています。

また、私はバックボーンを学んでいるだけなので、私は混乱の原因となる基本的な誤解があるかもしれません。

答えて

5

Hmは、すばやく見ました。あなたはこれが起こるのは間違いありませんし、それは標準的な練習ではありません。 理由は少しわかりにくいので、私に同行してください;)

todoアプリはbackbone-localstorageを使用しています。あなたはそれを呼び出すアプリで新しいアイテムを追加しようとすると:

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イベントがトリガされます。そのバックボーンのlocalStorageがcreateに次の処理を行いけれどもそれは起こる:

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

お知らせmodel.setがモデルにIDを与えます。これが(2番目の)changeイベントをトリガします。

あなたは何をするの作成変更することで、起きてからこれを停止することができます:

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

+1

良いキャッチ!..イベントトリガーを避けるために '{silent:true}'を使うこともできます。 – fguillen

+1

あなたが正しいのは、それが変更イベントが発生している理由です。ただし、提案した方法でコードを変更すると、イベントが停止するだけでなく機能が停止します(アイテムを削除できなくなります)。明らかにこれは私の質問に答える点ではあまり重要ではありませんが、将来の誰かがこれを読んでいる場合に備えて、私はそれを指摘したいと思います。 – jcady

+0

アイテムを削除する_permanently_です。削除後、私がリフレッシュすると、それらはまだ存在します。 – jcady

1

を再レンダリングしないでください。

デバッグもう少しお試しください。 ラッパー・メソッドように変更イベントをバインドするようにしてください:

initialize: function(){ 
    this.model.bind("change", this.renderWrapper, this); 
}, 

renderWrapper: function(){ 
    console.log("in the renderWrapper"); 
    this.render(); 
} 

第二render()変更イベントバインドのためではなく、他の理由のために作られた確かに。

+0

あなたが正しいです。私は私の質問で、最初は 'this.render()'の代わりに 'console.log( 'Change!')'を置くことでこれを絞り込んだことに留意すべきでした。それゆえ、私は変更イベントが発砲していると確信していました。 – jcady

関連する問題