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




backbone.js