22

Sto costruendo un'app ibrida utilizzando ionic e AngularJS (materiale AngularJS). Questa app ha anche una chat integrata con Node.js e socket.io.AngularJS: ripetizione virtuale con riga con altezze diverse

Ho il problema ora che con solo 200 messaggi l'app si scarica molto lentamente per caricare tutti i messaggi (200 ms in Browser -> 4sec in app, anche con CrossWalk e con track by message.id) e anche digitando la textarea per inserire il messaggio è rallentata.

ho due soluzioni per risolvere questo:

  1. Ripetere virtuale (md-virtual-repeat)
  2. Infinite Scroll (ione-infinite-scroll)

1) Penso che la ripetizione virtuale sarebbe la soluzione migliore (l'ho già implementata su un'altra pagina e scorre 1500 elementi come un incantesimo) ma il problema è che i messaggi possono avere altezze diverse in base alle loro lunghezze e i requisiti di md-virtual-repeat sono che tutti gli elementi devono avere la stessa altezza per w ork.

2) Quindi forse possiamo ruotare il metodo di scorrimento infinito ma il problema ora è che farlo con la direttiva ion-infinite-scroll diventa un po 'complicato dal momento che una chat ha bisogno di attivare loadMore() quando raggiunge la cima e non il fondo.

Quindi la mia domanda è: Qualcuno ha una soluzione per avere un/veloce ng-repeat liscia all'interno di una chat utilizzando o una direttiva virtual-repeat in grado di gestire diverse altezze o un rotolo infinito che lavora al inizio?

+0

Hai trovato una soluzione? – InsFi

risposta

1

Avete dato un'occhiata a React.js come soluzione? Utilizza un DOM virtuale che rende più efficiente l'aggiornamento di elenchi lunghi.

C'è un repository open source su GitHub che miscela Angular e React, chiamato ngReact.

panoramica: http://ngreact.github.io/ngReact/

docs: http://ngreact.github.io/ngReact/docs/ngReact.html

repo: https://github.com/ngReact/ngReact

Spero che questo aiuti.

+0

Personalmente non so Reagire e non l'ho mai usato. Se questo rivelasse la migliore soluzione, quanto tempo pensi che sarebbe necessario per impararlo? Sono un libero professionista e ho bisogno di correre contro il tempo per guadagnarsi da vivere –

+0

Questo dipende da quanto sei comodo con Angular. Se hai una buona padronanza di Angular, raccoglierlo non dovrebbe essere troppo difficile. – Matt

1

Utilizzando leganti separate come rivetti potrebbe essere una buona soluzione, la sua facile da integrare e il suo dover-rv ogni loop

+0

Potresti elaborare per favore (con un link forse)? –

+0

si prega di fare riferimento a questo [collegamento] (http://rivetsjs.com/), È un legante leggero e comparativamente veloce, Può essere d'aiuto per te, Il suo supporto semplice Javascript bidirezionale, Come usare è qui [link] (http : //justbuildsomething.com/agnostic-data-binding-with-rivets-js/) –

1

Penso che la direttiva ionica collection-repeat potrebbe essere quello che stai cercando.

collection-repeat consente a un'app di mostrare enormi elenchi di elementi molto più in modo performante rispetto a ng-repeat. Rappresenta nel DOM solo il numero di articoli così come sono attualmente visibili. Ciò significa che su uno schermo del telefono che può contenere otto elementi, verranno visualizzati solo gli otto elementi corrispondenti alla posizione corrente di scorrimento .

+0

"Se gli attributi item-height e width-item non vengono forniti, si presume che ogni elemento dell'elenco abbia le stesse dimensioni come il primo oggetto."- Un po 'problematico nel mio caso o pensi che possa essere corretto –

+0

L'ho provato ora ma se il primo messaggio è piccolo e metto un grande testo la bolla del messaggio si riduce e viceversa se il primo messaggio è grande –

+0

@Smile Applications forse funziona se si aggiunge la classe 'item-text-wrap' all'elemento messaggio. – nicfo

2

Un paio di cose che potresti provare ad accelerare.

Uno potrebbe essere quello di utilizzare qualcosa come rapido-ng-repeat: https://github.com/allaud/quick-ng-repeat invece di costruito in js angolare ng-repeat

Un'altra potrebbe essere quella di utilizzare one time binding dove mai possibile per evitare angolare da sempre alla ricerca di modifiche in ogni ciclo di digestione: https://docs.angularjs.org/guide/expression#one-time-binding

E, naturalmente, se possibile, provare a utilizzare l'opzione del profilo dello sviluppatore di Chrome per scoprire quali funzioni rallentano l'applicazione;)

PS: Potrebbe essere la pena di verificare questa discussione per vedere come inverso scrolling infinito potrebbe essere implementato: Implementing a reverse infinite scroll using ngInfiniteScroll directive in AngularJS

2

liste di scorrimento efficienti come md-virtual-repeat o collection-repeat hanno bisogno di conoscere l'altezza di ciascun elemento al fine di lavorare. Questo perché hanno bisogno di conoscere la posizione di scorrimento, ad es. per mostrare una barra di scorrimento o per poter saltare i fotogrammi per movimenti rapidi a scorrimento. La posizione di scorrimento di per sé può essere trovata solo se si conosce sia quanto è stato fatto scorrere (abbiamo bisogno dell'altezza degli elementi sopra) sia quanto è rimasto da scorrere (abbiamo bisogno dell'altezza degli elementi sotto).

Quello che puoi fare è usare una fabbrica per calcolare l'altezza di ogni elemento prima di iniettarli nel loop. Questo può essere fatto creando un contenitore con le stesse proprietà del contenitore di destinazione (ad esempio classi CSS), aggiungendo gli elementi appena caricati, calcolando la loro altezza (usando element.offsetHeight) e rimuovendo il contenitore dopo.

Si noti che questo è piuttosto pesante e probabilmente causerà un picco di ritardo.

+0

Sì, ho pensato anche a questo, visto che non ho alcuna lentezza 'problemi nella pagina (dato che ho usato track by id) ma ci vuole solo molto tempo per eseguire il rendering dei messaggi la prima volta, pensi che questo metodo sarà in realtà un miglioramento? –

+0

È decisamente un miglioramento rispetto a 'ng-repeat' se carichi come <30 elementi (messaggi) alla volta e il tuo elenco è in costante aumento! – Iso

+0

@Iso hai già implementato questo approccio o hai letto di qualcuno che esemplifica il modo in cui lo hanno fatto? –

0

Guarda angolare-vs-repeatangular-vs-repeat

Demo: demo

Io uso la lunghezza della linea per l'altezza calcolo delle voci.

È un metodo molto approssimativo. Nella nostra app sappiamo che un personaggio inglese con dimensione 15px di font avrà una larghezza di circa 6.7px (va bene, se usi il font monospace, ma non è il nostro caso). Inoltre conosciamo sempre la larghezza di ogni segmento e l'altezza di una riga di testo. itemHeight = commulativeTextLenght/lineWidth + paddingsOfItem; Anche lo stile di interruzione di linea può influire sul calcolo. In generale abbiamo avuto un metodo non male per calcolare altezze di circa 8000 paragrafi di testo.

+1

Leggere la sezione [Come rispondere] (http://stackoverflow.com/help/how-to-answer), in particolare questa sezione: ** Fornire il contesto per i collegamenti **. Cioè per esemplificare: spiega cosa fanno i collegamenti, e se hai la demo, includi il codice nella tua risposta. – AgataB

+0

Come si calcola l'altezza dell'elemento in base alla lunghezza della linea? Puoi fornire un esempio della tua soluzione? –