2015-01-24 4 views
12

Stellen Sie sich einige schwere Inhalte vor, die auf einer Webseite gerendert werden können, z. B. ein Diagramm. Angular gibt 2 Optionen, um die Sichtbarkeit des Inhalts umzuschalten.Angular ng-if und ng-show-Kombination

ng-show wird den Inhalt unabhängig von der Expression und einfach "verstecken" es nach der Tat. Dies ist nicht ideal, da der Benutzer den Inhalt während seiner Sitzung möglicherweise nie "öffnet", so dass es eine Verschwendung war, ihn zu rendern.

ng-wenn ist in dieser Hinsicht besser. Wenn Sie es anstelle von ng-show verwenden, wird verhindert, dass der schwere Inhalt überhaupt gerendert wird, wenn der Ausdruck falsch ist. Seine Stärke ist jedoch auch seine Schwäche, denn wenn der Benutzer das Diagramm ausblendet und es dann erneut anzeigt, wird der Inhalt jedes Mal von Grund auf neu gerendert.

Wie kann ich eine Richtlinie erstellen, die das Beste aus beiden Welten nutzt? Das bedeutet, dass es wie ng-if funktioniert, bis der Inhalt das erste Mal gerendert wird und dann wie ng-show arbeitet, um zu verhindern, dass es jedes Mal neu gerendert wird.

+1

ng-faul-Show: http://developers.lendio.com/ blog/combining-ng-if-und-ng-show-fuer-besser-angularjs-performance/ – rinogo

+0

Danke, dass genau das, was ich letztlich am Ende verwendet habe – parliament

Antwort

18

+1 auf Denis Antwort, sondern nur der Vollständigkeit halber Umwillen, es kann noch weiter vereinfacht werden, indem die Logik in der Ansicht ohne „verschmutzen“, um den Controller zu halten:

<button ng-click="show = !show">toggle</button> 
<div ng-if="once = once || show" ng-show="show">Heavy content</div> 

plunker

EDIT: die obige Version könnte weiter verbessert werden (und vereinfacht) mit einmaliger Bindung, um eine unnötige $ Uhr auf once zu reduzieren - das wird nur in Angular 1.3 funktionieren:

<div ng-if="::show || undefined" ng-show="show">Heavy content</div> 

Die undefined wird benötigt, um sicherzustellen, dass der überwachte Wert nicht "stabilize" ist, bevor er true wird. Sobald es stabilisiert ist, verliert es auch die $ Uhr, so dass es durch keine weitere Änderung an show beeinflusst würde.

+0

coole update, danke! – parliament

+0

Awesome Tipp, ich werde darüber nachdenken, wie man es in irgendeiner Weise wiederverwenden kann! – fjcero

+0

Toller Trick! Aber gibt es eine Möglichkeit, Richtlinien bei Bedarf erneut zu rendern? – kashesandr

9

Sie könnten es mit ngIf und ngShow zusammen machen, wo jeder Controller durch verschiedene Variable ist. ngIf wird einmal auf true gesetzt und nie wieder auf false gesetzt, während ngShow so oft umgeschaltet wird, wie der Benutzer möchte.

Werfen Sie einen Blick auf diese fiddle.

+0

hmmm touché sir – parliament

5

Es war die Antwort von @new-dev, die meine eigene Kombinationsidee dazu inspirierte, mit einem Toggle-Knopf eine ziemlich schwere Komponente schnell zu bekommen.

Mein ursprüngliches Problem war, dass meine Seite aus ~ 20 Komponenten besteht, die ~ 1 Sekunde zum Laden benötigen. Jedes wird durch eine Schaltfläche umgeschaltet.

Bei Verwendung von plain ng-wenn ich sofort nach dem Drücken einer Taste Laden und 1 Sekunde Verzögerung erhalten würde.

Wenn Ebene ng-Show mit I Instant-Kniehebelpressen, aber 20 Sekunden Seite Ladeverzögerung ...

So auch ich kombiniere sie mit einer ng-MouseEnter- Kontrolle geraten würde, jetzt. So was.

<div ng-mouseenter="create=true"> 
    <button ng-click="showAll = !showAll"></button> 
    <!--lightweight content--> 
    <div ng-show="showAll"> 
     <div ng-if="create"> 
      <!--Heavy content--> 
     </div> 
    </div> 
</div> 

Dies gab mir hervorragende Leistung in Chrom und IE.Die Zeit, die der Benutzer benötigt, um nach dem Eingeben der Komponente tatsächlich auf die Schaltfläche zu klicken, wird für die DOM-Erstellung verwendet. Und dann werden die DOM-Knoten schnell einmal angezeigt (wenn) der Klick ankommt.

Ich habe auch nie den ng-if-Ausdruck wieder auf false gesetzt. Halten Sie das DOM zwischengespeichert, wenn der Benutzer diesen Abschnitt wechselt.

aktualisieren: Der Grund, warum ich nicht über die ng-if und ng-Show auf dem gleichen div ist, dass im IE es Flimmern verursacht. Wenn das moonenter-Ereignis eintraf, würde es den Inhalt anzeigen und dann ausblenden. In Chrom war es in Ordnung, es auf demselben Div zu haben.

+0

Hallo, das sieht gut aus für meinen Fall. Ich kann ng-mouseenter aber nicht am Telefon benutzen oder kann ich? Was ist die Alternative? –

+0

Sie haben Recht, auf dem Telefon oder Tablet erzeugt es keine Geschwindigkeitsleistung. Nicht sicher, was ich dann benutzen soll. – tkarls

0

Sie könnten an einer benutzerdefinierten Direktive ng-lazy-show von Alan Colver interessiert sein. Es ermöglicht sowohl ng-if und ng-show Kombination:

<div ng-lazy-show="showFilters" lendio-business-filters></div> 

Der Code ist klein und leicht zu einem Projekt hinzugefügt werden können:

var ngLazyShowDirective = ['$animate', function ($animate) { 

    return { 
    multiElement: true, 
    transclude: 'element', 
    priority: 600, 
    terminal: true, 
    restrict: 'A', 
    link: function ($scope, $element, $attr, $ctrl, $transclude) { 
     var loaded; 
     $scope.$watch($attr.ngLazyShow, function ngLazyShowWatchAction(value) { 
     if (loaded) { 
      $animate[value ? 'removeClass' : 'addClass']($element, 'ng-hide'); 
     } 
     else if (value) { 
      loaded = true; 
      $transclude(function (clone) { 
      clone[clone.length++] = document.createComment(' end ngLazyShow: ' + $attr.ngLazyShow + ' '); 
      $animate.enter(clone, $element.parent(), $element); 
      $element = clone; 
      }); 
     } 
     }); 
    } 
    }; 

}]; 

angular.module('yourModule').directive('ngLazyShow', ngLazyShowDirective); 
Verwandte Themen