javascript - utilizado - minimize o trabalho da thread principal wordpress
Como melhorar o desempenho de renderização ao usar $.html() (1)
Eu estou trabalhando em um
aplicativo demo
Backbone que mostra uma lista de tweets.
Como estou substituindo todos os "tweets" por dados diferentes, limpo a lista usando
$.html()
render: function() {
$("#item-table").html('');
this.collection.each(this.addItem);
}
Eu queria saber se alguém poderia me dar uma dica com o que eu posso substituir este
$.html()
para um melhor desempenho, porque usando
$.html()
eu estou causando reflows e que dá maus tempos de processo de layout.
Existem dois outros lugares no código onde eu uso
$.html()
e seria ótimo se alguém pudesse me dar conselhos sobre como alterá-los também se esses outros lugares forem possíveis.
Create um novo DocumentFragment para pré-processar todos os itens e atualize o DOM uma vez.
Além disso, favorecer
this.$(...)
sobre o seletor jQuery global
$(...)
.
this.$
é um proxy para
this.$el.find(...)
que é mais eficiente e menos propenso a selecionar algo fora da view.
Usar a função principal do jQuery (
$()
) dentro de uma visualização pode falhar se a exibição ainda não foi renderizada.
Portanto, é melhor sempre manipular
this.$el
para que você possa fazer alterações mesmo antes de a exibição ser realmente colocada no DOM.
Mantenha todas as sub-vistas criadas em uma matriz para removê-las mais 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;
},
A otimização real começa aqui, com um contêiner temporário.
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;
},
Nossa função
renderItem
ainda pode ser usada para renderizar uma única visualização de item e imediatamente colocá-la no DOM.
Mas também fornece uma opção para adiar a manipulação do DOM e apenas retorna a visão.
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 vazamentos de memória com ouvintes pendentes, é importante chamar a
remove
em cada visualização antes de esquecê-la.
Eu uso uma otimização adicional, adiando a chamada real para
remove
para que não perca tempo agora enquanto o usuário aguarda.
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);
}
}