2012-01-21 8 views
6

Mam widok tabeli zadań, który wyświetla wszystkie zadania użytkownika. Funkcja pobierania kolekcji zadań() może potencjalnie zwrócić zawartość tysięcy rekordów. Uruchomiłem test i wstawiłem 1000 rekordów zadań do bazy danych i wykonałem funkcję pobierania() w kolekcji. Jednak 1000 rekordów wydaje się zbyt dużym obciążeniem dla przeglądarki, ponieważ wstawienie 1000 wierszy tabeli DOM wydaje się powodować zawieszenie się przeglądarki.Backbone.js fetch() duża kolekcja powoduje zatrzymanie skryptu

Czy istnieje lepszy sposób na zoptymalizowanie renderowania wierszy, aby działał szybciej? Wiem, że zawsze można wykonać częściowe pobranie (pobrać 100 początkowych rekordów i dodatkowo pobrać 100 rekordów za każdym razem, gdy użytkownik przewinie się na dół ekranu), ale ogólnie jestem przeciwny temu pomysłowi, ponieważ przewijam 100 rekordów i muszę poczekać 3 -4 sekundy przed renderowaniem dodatkowe 100 rekordów wydaje się powodować słabe wrażenia użytkownika.

Oto mój kod:

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

}); 

Odpowiedz

5

to wszystko zależy od tego, co doświadczają potrzeb użytkownika, co będzie musiał zrobić z pracy, Twój użytkownik, jest to potencjalny kandydat praca, która szuka pewna praca? czy jest to rodzaj aplikacji administracyjnej, w której użytkownik jest osobą zarządzającą pracą?

w ogólności umieszczenie 1000 elementów na 1 stronie jest złym userexperience, praca z ładowaniem dodatkowych zadań po przewinięciu to coś w rodzaju gorącej funkcji takich jak Facebook, Twitter ... to może być dobre dla komentarzy, ale praca jest czymś innym , potrzebny jest sposób przeskakiwania od początku do końca bez konieczności klikania "więcej" 10 razy lub przewijania w dół 10 razy.

możliwe rozwiązania:

  1. tak, stronicowania jest oczywiście inna opcja, za pomocą pagera jest defenately sposób pracować ze zbyt wielu elementów, a dając człowiekowi drogę do skoku od strony 1 do 10 bez przechodząc przez 9 innych.
  2. Inną rzeczą, którą możesz zrobić, to zbudować filtry, można wyszukiwać zadania według: lokalizacji, firmy, sektora, ... to zmniejszy rozmiar kolekcji, która jest widoczna przez cały czas.

czyste rozwiązania techniczne:

powinieneś przeczytać na this blog post, to zaczyna się, jak uzyskać dokładny kliknięty element z widokiem jeśli renderowane wszystkie elementy kolekcji w zaledwie 1 widzenia, ale ewoluuje problem tutaj pod ręką, mający 1000 oddzielnych widoków 1 na zadanie dodawanych do jobListView lub posiadających te zadania dodane w jobListView, więc istnieje tylko 1 widok.

Te ostatnie mogą zostać poprawnie zaimplementowane, co znacznie zmniejszy interakcję aplikacji z DOM. Z poprawnie zaimplementowanym mam na myśli, dodając wszystkie zadania w pętli for, dodając je do tabeli/listy w pamięci, i tylko na samym końcu dołącz tabelę/listę do DOM, to redukuje twój kod do 1 interakcji DOM zamiast 1000 dołącza.

Tak, Derick chudnie bardziej w kierunku renderowania 1 widoku na model, ale nie dotyka tematu wydajności, z wyjątkiem małego: najpierw spraw, aby to było szybkie stwierdzenie, które nie zapewnia żadnych rozwiązań dla ciebie. A jeśli twoja lista zleceń jest tylko wykazem i linkiem do strony szczegółów zadania, bez wielu zdarzeń, widok 1, aby rządzić wszystkimi tymi opcjami jest nadal bardzo ważny.

+0

Próbowałem tego przykładu w poście na blogu i nie wydaje się, że znacznie poprawia wydajność. Niezależnie od tego, czy dodajesz do DOM, czy dołączasz do elementu w pamięci, nadal wywołujesz jQuery's append() 1000 razy – peter

+0

tak, ale dodanie jquery bez robienia tego w domenie jest szybsze. mimo to istnieją jeszcze lepsze rozwiązania, może wyglądać brudno, ale budowanie html ręcznie (lub z szablonami) i zrobić $ (elem) .html (myBuildUpHtmlString); jest jeszcze szybszy, niż Ty nie masz 1000 załączników. – Sander

2

Twoja słaba wydajność prawdopodobnie wynika z tego, że dodajesz wiersze bezpośrednio do DOM. Za każdym razem, gdy to zrobisz, przeglądarka się rozpłynie.

Chciałbym zbudować tabelę w pamięci, a następnie dodać całą tabelę do DOM po jego skonstruowaniu.