2014-11-18 5 views
18

Ich verwende Ionic und möchte die Hintergrundfarbe jedes Elements in einem <ion-list> basierend auf den Daten dynamisch ändern. Ich dachte ich, das von einem Funktionsaufruf durch täte die richtige KlasseVerwenden von ng-Klasse mit einem Funktionsaufruf - mehrmals aufgerufen

<ion-list> 
    <ion-item ng-repeat="singleCase in allCases" ng-class="getBackgroundColour(singleCase)" class="item-avatar"> 
    <h2>{{singleCase.date}}</h2> 
    <p>{{singleCase.caseType}}</p> 
    </ion-item> 
</ion-list> 

Dies ist der Controller derzeit

.controller('AllCasesCtrl', ['$scope', '$log', 'dummyData', function($scope, $log, dummyData) { 
    $scope.allCases = dummyData.cases; 

    $scope.getBackgroundColour = function(singleCase){ 

     $log.log("getBackgroundColour called...singleCase type: " + singleCase.speciality); 

     var colourMap = { 
     speciality1: "speciality1Class", 
     speciality2: "speciality2Class", 
     speciality3: "speciality3Class" 
     }; 

     return colourMap[singleCase.speciality]; 
    }; 

    }]) 

Auf die Überprüfung der Konsole zurückzukehren, die getBackgroundColour() Funktion aufgerufen wird 7 Zeiten für jede <ion-item> in der Liste. Warum ist das, und sollte ich vermeiden, einen Funktionsaufruf in ng-class zu verwenden?

Antwort

23

AngularJS arbeitet mit dirty checking: es braucht jedem Zyklus die Funktion aufgerufen werden um sicher zu sein, dass es keinen neuen Wert zurückgibt und dass die DOM muss nicht aktualisiert werden.

Es ist Teil des typischen Prozesses des Frameworks, und eine Funktion so einfach wie Ihre sollte keine negativen Auswirkungen auf die Leistung haben. Lesbarkeit und Testbarkeit Ihres Codes ist hier viel wichtiger, also behalten Sie die Logik in Ihrem Controller.

Eine einfache Dinge zu tun, aber einfach ist die Erklärung von colourMap zu bewegen, die eine Konstante ist, außerhalb Ihrer Funktion:

var colourMap = { 
    speciality1: "speciality1Class", 
    speciality2: "speciality2Class", 
    speciality3: "speciality3Class", 
}; 

$scope.getBackgroundColour = function(singleCase) { 
    return colourMap[singleCase.speciality]; 
}; 
+0

Sagen wir, ich habe 100 generierte Elemente, es ruft meine Funktion 100 * auf 100 = 10 000 mal. Gibt es eine andere Lösung, um das Dirty Checking System zu umgehen? Als Neuling mit AngularJS habe ich gesehen, dass die Vererbung zwischen Controllern verwendet werden kann, um Daten zu speichern, aber ich weiß nicht, ob es eine "Best Practice" ist. Kann mir jemand Licht dazu bringen? thx – Alex

+2

@Alex Woher kommt die zweite "100" in Ihrem Kalkül? Du kannst deine Ausdrücke nur einmal bewerten, wenn du weißt, dass sie sich nicht ändern (das ist die [faul einmalige Bindung] (http://stackoverflow.com/q/23969926/2057033)), aber du kannst nicht "umgehen" das schmutzige Kontrollsystem. Woher weißt du, dass sich deine Werte geändert haben? – Blackhole

+0

Ja, ich habe das ein bisschen zu schnell geschrieben. Ich wollte sagen, dass die Funktion (100 + 99 + 98 + 97 ... + 2 + 1) mal aufgerufen wird (mit meinem 100-Elemente-Beispiel). Durch die Umgehung des dreckigen Kontrollsystems ist es hier mein schlechtes Englisch, das mich betrogen hat. Ich wollte fragen, ob es einen Weg gibt, den Wert nur einmal zu überprüfen, indem ich einen anderen Ansatz verwende. Und schließlich, vielen Dank für Ihre faule einmalige Bindung, werde ich das durchsehen. – Alex

8

Ihr Weg ist in Ordnung, solange Ihre Liste nicht eine riesige Größe ist. Wenn Sie angle 1.3 verwenden und die Anzahl der Aufrufe verringern möchten, können Sie Ihre ng-Klasse in ng-class = ":: getBackgroundColour (singleCase)" ändern. Dies gilt einmal verbindlich. Sobald der Wert stabil ist, wird er nicht erneut überprüft. Dies würde höchstwahrscheinlich zwei Aufrufe pro Artikel bedeuten.

+0

Dank, müssen über diese gehen und zu lesen. Die Klassen sollten sehr stabil bleiben, damit ich es versuchen kann. Aber wenn der Benutzer geht und die Daten ändert, müsste die Klasse aktualisiert werden ... würde die einmalige Bindung dies brechen? – drjimmie1976

+0

Solange Sie keine einmalige Bindung für die Variable allCases verwenden, wird sie erneut aufgerufen, da die ng-Wiederholung ausgeführt wird und neue dom-Elemente erstellt werden. – Jason