2012-01-21 8 views
6

Ho una vista tabella Lavori che visualizza tutti i lavori di un utente. La raccolta di lavori fetch() può potenzialmente restituire contenere migliaia di record. Ho eseguito un test e inserito 1000 record di lavoro nel DB ed eseguito un recupero() sulla raccolta. Tuttavia, 1000 record sembrano troppo da gestire per il browser poiché l'inserimento di 1000 righe della tabella DOM sembra causare il blocco del browser.Backbone.js fetch() la raccolta di grandi dimensioni causa il blocco dello script

C'è un modo migliore per ottimizzare il rendering delle righe in modo che funzioni più velocemente? So che puoi sempre eseguire un recupero parziale (recupera fino a 100 record e inoltre recupera 100 record ogni volta che l'utente scorre verso la parte inferiore dello schermo), ma di solito sono contrario a questa idea, poiché lo scorrimento di 100 record e il dover attendere 3 -4 secondi prima che vengano visualizzati altri 100 record sembrano avere un'esperienza utente scadente.

Ecco il mio codice:

FM.Views.JobTable = Backbone.View.extend({ 
    initialize: function(){ 
    _.bindAll(this, 'render', 'refresh', 'appendItem'); 
    this.collection.bind('add', this.appendItem, this); 
    this.collection.bind('reset', this.refresh, this); 
    }, 

    render: function(){ 
    this.el = ich.JobTable({}); 
    $(this.el).addClass('loading'); 
    return this; 
    }, 

    refresh: function(){ 
    $('tbody tr', this.el).remove(); 
    $(this.el).removeClass('loading'); 

    _(this.collection.models).each(function(item){ // in case collection is not empty 
     this.appendItem(item); 
    }, this); 
    return this;  
    }, 

    appendItem: function(item){ 
    var jobRow = new FM.Views.JobTableRow({ 
     model: item 
    }); 
    $('tbody', this.el).prepend(jobRow.render().el); 
    $(jobRow).bind('FM_JobSelected', this.triggerSelected); 
    } 

}); 

FM.Views.JobTableRow = Backbone.View.extend({ 
    tagName: 'tr', 

    initialize: function(){ 
    _.bindAll(this, 'render', 'remove', 'triggerSelected'); 
    this.model.bind('remove', this.remove); 
    }, 

    render: function(){ 
    var j = this.model.toJSON(); 
    j.quantity = j.quantity ? number_format(j.quantity, 0) : ''; 
    j.date_start = date('M j Y', j.date_start); 
    j.date_due = j.date_due ? date('M j Y', strtotime(j.date_due)) : ''; 
    j.paid_class = j.paid; 
    j.status_class = j.status; 
    j.paid = slug2words(j.paid); 
    j.status = slug2words(j.status); 

    this.el = ich.JobTableRow(j); 
    $(this.el).bind('click', this.triggerSelected); 
    return this; 
    } 

}); 

risposta

5

tutto dipende da ciò che l'esperienza le esigenze degli utenti, cosa che ha a che fare con i lavori, l'utente, è un potenziale candidato di lavoro che è alla ricerca di un certo lavoro? o è una specie di app di amministrazione in cui l'utente è qualcuno che gestisce i lavori?

in generale mettere 1000 articoli su 1 pagina non è buona userexperience, lavorare con il caricamento di lavori aggiuntivi su scroll down è una specie di funzione molto calda in questi giorni come facebook, twitter ... questo potrebbe essere buono per i commenti, ma i lavori sono qualcos'altro , è necessario un modo per saltare dall'inizio alla fine senza dover fare clic su "altro" 10 volte, o scorrere verso il basso 10 volte.

possibili soluzioni:

  1. così, paging è ovviamente un'altra opzione, utilizzando un pager è senza dubbio in quest'hotel un modo per lavorare con troppi elementi, e dare alla persona un modo per saltare da pagina 1 a 10, senza passando attraverso gli altri 9.
  2. Un'altra cosa che puoi fare è creare filtri, puoi cercare lavori per: posizione, azienda, settore, ... questo ridurrà la dimensione della collezione che è visibile in ogni momento.

puri soluzioni tecniche:

si dovrebbe leggere su this blog post, inizia su come ottenere l'oggetto esatto cliccato da una vista se hai reso tutti gli elementi di una collezione in appena 1 visita, ma si evolve in il problema è qui, con 1000 viste separate 1 per lavoro da aggiungere a jobListView, o avere quei lavori aggiunti all'interno di jobListView in modo che ci sia solo una vista.

Quest'ultimo, se implementato correttamente, riduce notevolmente l'interazione della tua app con il DOM. Con implementato correttamente voglio dire, aggiungendo tutti i lavori in un ciclo for, aggiungendoli a una tabella/elenco in memoria, e solo alla fine, allegare la tabella/elenco nel DOM, questo riduce il codice a 1 interazione DOM , piuttosto che 1000 appendi.

Sì, Derick si inclina di più verso il rendering di 1 vista per modello, sebbene non tocchi l'argomento della prestazione tranne che per un piccolo: prima rendilo quindi rendi una dichiarazione veloce che non fornisce alcuna soluzione per te. E se il tuo elenco di lavori è solo un elenco e un collegamento alla pagina dei dettagli del lavoro, senza molti eventi, l'opzione 1 per domarli tutti è ancora molto valida.

+0

Ho provato l'esempio nel post del blog e non sembra migliorare molto le prestazioni. Sia che si acceda al DOM o si acceda a un elemento in memoria, si sta ancora chiamando jQuery's append() 1000 volte – peter

+0

sì, ma jquery append senza farlo al dom stesso è più veloce. anche così, ci sono ancora soluzioni migliori, potrebbe sembrare sporco, ma costruire manualmente il tuo html (o con i modelli) e fare un $ (elem) .html (myBuildUpHtmlString); è ancora più veloce, quindi non hai 1000 allegati. – Sander

2

Le tue scarse prestazioni sono probabilmente dovute all'aggiunta di righe direttamente al DOM. Ogni volta che lo fai, il browser si rifletterà.

Vorrei costruire la tabella in memoria e quindi aggiungere l'intera tabella al DOM una volta costruita.

Problemi correlati