2017-05-17 5 views
1

Ich arbeite an einem Backbone demo app, das eine Liste von Tweets zeigt. Als ich all die „Tweets“ mit unterschiedlichen Daten bin ersetzt lösche ich die Liste mit $.html()

render: function() { 
    $("#item-table").html(''); 
    this.collection.each(this.addItem); 
} 

ich mich gefragt, ob jemand mir einen Hinweis mit geben könnte, was kann ich diese ersetzen $.html() für eine bessere Leistung, denn durch $.html() mit Ich verursache Reflows und die Layout-Prozesszeiten sind schlecht.

Es gibt zwei andere Orte in dem Code, wo ich $.html() verwende und es wäre wirklich toll, wenn jemand mir Ratschläge geben könnte, wie man diese auch ändert, wenn diese anderen Orte sogar möglich sind.

Antwort

3

Create ein neues DocumentFragment, um alle Elemente vorzurendern, dann aktualisieren Sie das DOM einmal.

Auch zugunsten this.$(...) über den globalen jQuery-Selektor $(...).

this.$ ist ein Proxy zu this.$el.find(...), die effizienter und weniger anfällig ist, etwas außerhalb der Ansicht zu wählen.

Die Verwendung der Kernfunktion von jQuery ($()) in einer Ansicht kann fehlschlagen, wenn die Ansicht noch nicht gerendert wurde. Es ist also besser, immer durch this.$el zu manipulieren, damit Sie Änderungen vornehmen können, bevor die Ansicht tatsächlich in das DOM eingefügt wird.

Behalten Sie alle Unteransichten, die in einem Array erstellt wurden, um sie später sauber zu entfernen.

initialize: function() { 
    this.childViews = []; 
}, 
render: function() { 
    // cache the list jQuery object 
    this.$list = this.$("#item-table"); 

    // Make sure to destroy every child view explicitely 
    // to avoid memory leaks 
    this.cleanup(); 

    this.renderCollection(); 
    return this; 
}, 

Die eigentliche Optimierung beginnt hier mit einem temporären Container.

renderCollection: function() { 
    var container = document.createDocumentFragment(); 

    this.collection.each(function(model) { 
     // this appends to a in memory document 
     container.appendChild(this.renderItem(model, false).el); 
    }, this); 

    // Update the DOM only once every child view was rendered. 
    this.$list.html(container); 
    return this; 
}, 

Unsere renderItem Funktion kann weiterhin verwendet werden, um ein einzelnes Element Ansicht zu machen und es sofort in den DOM setzen. Aber es bietet auch eine Option, um die DOM-Manipulation zu verschieben, und es gibt nur die Ansicht zurück.

renderItem: function(model, render) { 
    var view = new Item({ model: model }); 

    this.childViews.push(view); 
    view.render(); 
    if (render !== false) this.$list.append(view.el); 
    return view; 
}, 

Um Speicherlecks mit baumelnden Hörer zu vermeiden, ist es wichtig, remove auf jeder Ansicht aufrufen, bevor über sie zu vergessen.

Ich nutze eine zusätzliche Optimierung, indem ich den eigentlichen Anruf auf remove verschiebe, damit wir keine Zeit verschwenden, während der Benutzer wartet.

+0

Vielen Dank! Ich werde einen Benchmark für diese App im Vergleich zu React (virtuelles DOM) machen, und ich benutze diese Backbone-App als ein Beispiel für KVO (Schlüssel-Wert-Beobachtung) View-Model-Synchronisationsmechanismus. Ich möchte nur sicher sein - wenn ich diese Optimierungen implementiere, wird diese App immer noch ein gutes Beispiel für den KVO View-Model Synchronisationsmechanismus sein? – gfels

+0

@gfels Es tut mir leid, ich bin nicht vertraut mit KVO View-Modell Synchronisationsmechanismus. Für den Vergleich von Backbone-Rendering mit React ist es irrelevant, da Backbone kein Rendering zur Verfügung stellt. Es bleibt dem Entwickler überlassen, was immer er möchte. Backbone bietet standardmäßig nur jQuery an, erlaubt dem Entwickler jedoch, das App-Rendering zu implementieren. –

+0

@gfels Wenn Sie mit _KVO view-model syncing mechanism_ eine Zweiwege-Datenbindung meinen, dann bietet Backbone das auch nicht an, und es gibt Bibliotheken, die darauf spezialisiert sind und leicht mit Backbone verwendet werden können. (Epoxy, Knockout, Rückgrat.Stickit, sogar React könnte verwendet werden) –

Verwandte Themen