2013-07-10 3 views
9

Ich habe versucht, Filter zu schreiben, aber es war ziemlich frustrierend.

Hier sind ein paar Ressourcen, die ich ein ‚Brocken‘ zum Schreiben

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

ich es ausprobiert mit einigem Erfolg filtern folgte. aber festgestellt, dass es einen Unterschied im Verhalten zwischen Versionen gibt

Die Methoden, die beschrieben werden, um einen $$ HashKey zu erzeugen, funktionieren nicht in der Version 1.1.5. Die erste Geige ist in Ordnung, während der zweite in Iterationsfehler erzeugt, obwohl der Code ist genau das gleiche:

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

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

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"]] 

Gibt es Workarounds/richtige Art, dies zu schreiben?

Antwort

12

Beginnend mit Version 1.1.4 hat die ng-repeat Direktive eine Überwachung der Sammlung, die Sie durchlaufen, um sicherzustellen, dass sie sich nicht geändert hat. Es funktioniert so, dass es jedes Element im Array vergleicht und wenn die Elemente nicht gleich sind (im Sinne von ===), denkt es, dass die Sammlung aktualisiert wurde. Zumindest verstehe ich das, nachdem ich den Code angeschaut habe.

Wenn Sie einen Filter im typischen Sinne verwenden, bei dem Sie nur eine Teilmenge der ursprünglichen Elemente zurückgeben, sind die zurückgegebenen Elemente jedes Mal gleich. Da Sie jedoch eine ganz neue Struktur erstellen, sind die Elemente im Array jedes Mal anders (auch wenn ihr Inhalt identisch ist). Daher denkt die Uhr, dass sich die Sammlung ständig ändert.

Die einzige Lösung, die ich finden konnte, war, einen Cache von zuvor zurückgegebenen Ergebnissen zu erstellen. Jedes Mal, wenn der Chunk-Filter aufgerufen wird, prüft er, ob Sie zuvor einen Filter mit demselben Array und derselben ChunkSize durchgeführt haben. Wenn dies der Fall ist, wird das zwischengespeicherte Ergebnis zurückgegeben.

Um dies zu tun, sollten Sie Ihre Filterfunktion aktualisieren etwas wie folgt aussehen:

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

ich auch darauf hinweisen, dass Sie wahrscheinlich die defineHashKeys Anruf entfernen kann, weil ich es nicht glaube, dient jede Zweck in diesem Code. Ich habe es nur da gelassen, weil es in Ihrem ursprünglichen Code war. Es schien keinen Unterschied zu machen, als ich es entfernte.

+0

Danke James! Mit dem Cache ... Was passiert, wenn mehrere Chunk-Filter auf der Seite vorhanden sind? Ich habe hier einen kleinen Versuch gemacht http://jsfiddle.net/nRGTX/42/ und es scheint für 2 Chunk-Filter zu funktionieren, aber ich frage mich, warum das der Fall ist, da ich erwartet hätte, dass die Filter sich gegenseitig überlisten – zcaudate

+0

I testete mit mehreren Filtern - die Lösung wurde so konzipiert, dass sie funktioniert. Beachten Sie, dass der Cache für jede Kombination aus Array und ChunkSize einen separaten Eintrag speichert, sodass zwei Filter mit unterschiedlichen Größen oder unterschiedlichen Arrays nicht in Konflikt stehen sollten. –

Verwandte Themen