2013-07-10 3 views
9

Ho cercato di scrivere filtri ma è stato piuttosto frustrante.

Qui ci sono un paio di risorse stavo seguendo per la scrittura di un 'pezzo' Filter

https://groups.google.com/forum/#!topic/angular/IEIQok-YkpU https://groups.google.com/forum/#!topic/angular/gEv1-YV-Ojg

ho provato con un certo successo. ma ho riscontrato differenze di comportamento tra le versioni

I metodi descritti per produrre un hashKey $$ non funzionano nella versione 1.1.5. Il primo violino è soddisfacente, mentre il secondo produce errore iterazione, anche se il codice è esattamente lo stesso:

http://jsfiddle.net/nRGTX/38/ - 1.0.3 versione

http://jsfiddle.net/nRGTX/39/ - 1.1.5 versione

Error: 10 $digest() iterations reached. Aborting! 
Watchers fired in the last 5 iterations: [["fn: $watchCollectionWatch; newVal: 16; oldVal: 14"],["fn: $watchCollectionWatch; newVal: 18; oldVal: 16"],["fn: $watchCollectionWatch; newVal: 20; oldVal: 18"],["fn: $watchCollectionWatch; newVal: 22; oldVal: 20"],["fn: $watchCollectionWatch; newVal: 24; oldVal: 22"]] 

Ci sono soluzioni alternative/modo corretto per scrivere questo?

risposta

12

A partire dalla versione 1.1.4 la direttiva ng-repeat ha un orologio sulla raccolta che si sta iterando per assicurarsi che non sia stato modificato. Il modo in cui funziona è che mette a confronto ogni elemento dell'array e se gli elementi non sono uguali (nel senso ===), pensa che la raccolta sia stata aggiornata. Almeno questa è la mia comprensione dall'aver visto il codice.

Se si utilizza un filtro nel senso tipico, in cui si restituisce solo un sottoinsieme degli elementi originali, gli articoli restituiti saranno sempre gli stessi. Tuttavia, poiché stai costruendo una struttura completamente nuova, gli elementi nell'array sono sempre diversi (anche se il loro contenuto è lo stesso), quindi l'orologio pensa che la collezione cambi continuamente.

L'unica soluzione che potevo ottenere era creare una cache dei risultati restituiti in precedenza. Ogni volta che viene chiamato il filtro chunk, controlla se hai precedentemente eseguito un filtro con lo stesso array e chunkSize. In tal caso, restituisce il risultato memorizzato nella cache.

Per fare questo, è necessario aggiornare la funzione di filtro per essere simile a questa:

return function(array, chunkSize) { 
    if (!(array instanceof Array)) return array; 
    if (!chunkSize) return array; 

    // Create empty cache if it doesn't already exist. 
    if (typeof myApp.chunkCache === "undefined") { 
    myApp.chunkCache = []; 
    } 

    // Search the cache to see if we filtered the given array before. 
    for (var i = 0; i < myApp.chunkCache.length; i++) { 
    var cache = myApp.chunkCache[i]; 
    if (cache.array == array && cache.chunkSize == chunkSize) { 
     return cache.result; 
    } 
    } 

    // If not, construct the chunked result. 
    var result = chunkArray(array, chunkSize); 
    defineHashKeys(result); 

    // And then add that result to the cache. 
    var cache = { 
    array: array, 
    chunkSize: chunkSize, 
    result: result 
    }; 
    myApp.chunkCache.push(cache); 

    return result; 
} 

Vorrei anche sottolineare che probabilmente si può rimuovere la chiamata defineHashKeys, perché io non credo che serve qualsiasi scopo in questo codice. L'ho lasciato solo perché era nel tuo codice originale. Non sembrava fare alcuna differenza quando l'ho rimosso.

+0

Grazie James! Con la cache ... cosa succede se ci sono più filtri nella pagina? Ho fatto una piccola prova qui http://jsfiddle.net/nRGTX/42/ e sembra funzionare per 2 filtri di blocco, ma mi chiedo perché questo è il caso in quanto mi sarei aspettato che i filtri si sovrapponessero a vicenda – zcaudate

+0

I ha fatto test con più filtri - la soluzione è stata progettata per funzionare in questo modo. Si noti che la cache memorizza una voce separata per ogni combinazione di array e chunkSize, quindi due filtri con dimensioni diverse o array diversi non dovrebbero essere in conflitto. –

Problemi correlati