Cómo mejorar el rendimiento del renderizado al usar $ .html ()

Estoy trabajando en una aplicación de demostración Backbone que muestra una lista de tweets. Como estoy reemplazando todos los “tweets” con datos diferentes, borro la lista usando $.html()

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

Me preguntaba si alguien podría darme una pista con respecto a qué puedo reemplazar este $.html() para un mejor rendimiento, porque al usar $.html() estoy causando reflujos y lo que da malos tiempos de proceso de disposición.

Hay otros dos lugares en el código donde uso $.html() y sería genial si alguien pudiera darme consejos sobre cómo cambiarlos si esos otros lugares son posibles.

Cree un nuevo DocumentFragment para preprocesar todos los elementos, luego actualice el DOM una vez.

Además, favorezca this.$(...) sobre el selector jQuery global $(...) .

this.$ es un proxy para this.$el.find(...) que es más eficiente y menos propenso a seleccionar algo fuera de la vista.

El uso de la función central de jQuery ( $() ) dentro de una vista puede fallar si la vista aún no se procesó. Por lo tanto, es mejor manipular siempre con this.$el para que pueda realizar cambios incluso antes de que la vista se ponga realmente en el DOM.

Mantenga todas las subvistas creadas en una matriz para eliminarlas limpiamente más tarde.

 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; }, 

La optimización real comienza aquí, con un contenedor temporal.

 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; }, 

Nuestra función renderItem todavía se puede usar para representar una vista de elemento individual y colocarlo inmediatamente en el DOM. Pero también proporciona una opción para posponer la manipulación DOM y simplemente devuelve la vista.

 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; }, 

Para evitar memory leaks con oyentes que cuelgan, es importante llamar a remove en cada vista antes de olvidarse de ello.

Utilizo una optimización adicional posponiendo la llamada real a remove para no perder tiempo ahora mientras el usuario espera.

 cleanup: function() { var _childViewsDump = [].concat(this.childViews); this.childViews = []; while (_childViewsDump.length > 0) { var currentView = _childViewsDump.shift(); // defer the removal as it's less important for now than rendering. _.defer(currentView.remove.bind(currentView), options); } }