Rozumiesz opcję wykluczenia definicji dyrektywy?

195

Myślę, że jest to jedna z najtrudniejszych do zrozumienia dla mnie przez dyrektywę angularjs.

Dokument z http://docs.angularjs.org/guide/directive mówi:

tranclude - skompiluj zawartość elementu i udostępnij ją dyrektywie. Zwykle używany z ngTransclude. Zaletą transkluzji jest to, że funkcja łączenia odbiera funkcję transkluzji, która jest wstępnie związana z odpowiednim zakresem. W typowej konfiguracji widget tworzy zakres izolowany, ale transkluzja nie jest dzieckiem, ale rodzeństwem zakresu izolowanego. Dzięki temu widget może mieć stan prywatny, a transkluzja może być powiązana z nadrzędnym (wstępnie izolowanym) zakresem.

  • true - uwzględnij treść dyrektywy.
  • „element” - należy objąć cały element, w tym wszelkie dyrektywy zdefiniowane o niższym priorytecie.

Mówi transcludezwykle używane z ngTransclude. Ale próbka z dokumentu ngTransclude w ogóle nie używa ngTranscludedyrektywy.

Chciałbym kilka dobrych przykładów, które pomogą mi to zrozumieć. Dlaczego tego potrzebujemy? Co to rozwiązuje? Jak tego użyć?

Freewind
źródło
FYI ... link działa przynajmniej teraz
Sandy

Odpowiedzi:

518

Rozważmy dyrektywę o nazwie myDirective w elemencie, a ten element zawiera inne treści, powiedzmy:

<div my-directive>
    <button>some button</button>
    <a href="#">and a link</a>
</div>

Jeśli myDirective używa szablonu, zobaczysz, że treść <div my-directive>zostanie zastąpiona szablonem dyrektywy. Więc mając:

app.directive('myDirective', function(){
    return{
        template: '<div class="something"> This is my directive content</div>'
    }
});

spowoduje to renderowanie:

<div class="something"> This is my directive content</div> 

Zauważ, że zawartość twojego oryginalnego elementu <div my-directive> zostanie utracona (lub lepiej mówiąc, zastąpiona). Pożegnaj się z tymi kumplami:

<button>some button</button>
<a href="#">and a link</a>

A co, jeśli chcesz zachować swój <button>...i <a href>...w DOM? Będziesz potrzebował czegoś zwanego transkluzją. Pomysł jest dość prosty: dołącz zawartość z jednego miejsca do drugiego . Więc teraz twoja dyrektywa będzie wyglądać mniej więcej tak:

app.directive('myDirective', function(){
    return{
        transclude: true,
        template: '<div class="something"> This is my directive content</div> <ng-transclude></ng-transclude>'
    }
});

To by renderowało:

<div class="something"> This is my directive content
    <button>some button</button>
    <a href="#">and a link</a>
</div>. 

Podsumowując, w zasadzie używasz opcji transclude, gdy chcesz zachować zawartość elementu, gdy używasz dyrektywy.

Mój przykład kodu jest tutaj . Można również korzystać z oglądania tego .

odiseo
źródło
12
Wygląda na to, że nieco zmienili funkcjonalność. Przynajmniej w wersji> = 1.2.9. Treść z szablonu nie jest dodawana do renderowanej treści. Zobacz odpowiedź @ TechExplorer poniżej
Tarjei Romtveit
20
Bardzo, bardzo dobra odpowiedź. Znacznie powyżej normy. Masz dobre przykłady, a twoje „to jest moja treść dyrektywy” bardzo ułatwiło czytanie w renderowanej wersji. Nie rozumiem, dlaczego Angular musi używać złożonej terminologii i pojęć, a następnie nie zawierać łatwych do zrozumienia przykładów takich jak Twoja. +2
bezpłatnie,
Czy ktoś wie, czy treść zawarta w transkrypcji może odnosić się do izolowanych pól zakresu dyrektywy? Mówi powyżej, że transkluzja jest rodzeństwem, a nie dzieckiem o izolowanym zasięgu ... więc zakładam, że nie może - ale zastanawiałem się, czy ktoś mógłby potwierdzić lub dać mi znać, jeśli jest to możliwe
Simon Green
@UladzimirHavenchyk dzięki, przenieśli wideo w inne miejsce. Poprawiłem link odpowiednio.
odiseo
4
@odiseo, czy mógłbyś napisać WSZYSTKIE dokumenty Angulara prostym, prostym do zrozumienia angielskim w ten sposób! + wiele 1.
Dan Hodson,
76

Myślę, że ważne jest, aby wspomnieć o zmianach powyższego zachowania w nowej wersji AngularJS. Spędziłem godzinę próbując osiągnąć powyższe wyniki w Angular 1.2.10.

Zawartość elementu z ng-tranclude nie jest dołączana, ale całkowicie zastępowana.

Tak więc w powyższym przykładzie to, co osiągnąłbyś dzięki „transkludowaniu”, to:

<div class="something">
    <button>some button</button>
    <a href="#">and a link</a>
</div>

i nie

<div class="something"> This is my directive content
    <button>some button</button>
    <a href="#">and a link</a>
</div>

Dzięki.

TechExplorer
źródło
Aby uzyskać więcej informacji na temat zmienionego zachowania w programie Angular 1.2, zobacz zmianę eed299a .
Mark Rajcok
37

To, co mówi TechExplorer, jest prawdą, ale możesz mieć obie treści, włączając w szablonie prosty znacznik kontenera (jak div lub span) z atrybutem ng-tranclude. Oznacza to, że następujący kod w szablonie powinien zawierać całą treść

<div class="something"> This is my directive content <div class="something" ng-transclude></div></div>
goulpan
źródło
5
To była kluczowa informacja, której brakowało w innych odpowiedziach
Matheus
4
Ta odpowiedź dodaje tyle informacji. ng-transcludeto atrybut, który działa jak symbol zastępczy, w którym umieszczane będą treści zawarte w transkluzji.
BeingSuman
5

Z Wiki:

„W informatyce transkluzja to włączenie części lub całości dokumentu elektronicznego do jednego lub większej liczby innych dokumentów przez odniesienie.”

Chciałbym dodać inne zastosowanie do transkluzji, a mianowicie to, że zmienia ona kolejność wykonywania funkcji kompilacji i łączenia dyrektyw nadrzędnych i podrzędnych. Może to być przydatne, gdy chcesz skompilować podrzędny DOM przed nadrzędnym DOM, ponieważ nadrzędny DOM może być zależny od podrzędnego DOM. Ten artykuł jest bardziej szczegółowy i bardzo dobrze wyjaśniony!

http://www.jvandemo.com/the-nitty-gritty-of-compile-and-link-functions-inside-angularjs-directives-part-2-transclusion/

Samir Alajmovic
źródło
5

Zaktualizowane angularjs 1.6.6 Dokumentacja ma teraz lepszego wyjaśnienia.

Transclude służy do utworzenia dyrektywy, która otacza inne elementy

Czasami pożądane jest, aby móc przekazać cały szablon zamiast ciągu lub obiektu. Powiedzmy, że chcemy stworzyć komponent „okna dialogowego”. Okno dialogowe powinno umożliwiać zawijanie dowolnych treści.

Aby to zrobić, musimy użyć opcji tranclude . Zobacz przykład poniżej.


script.js

angular.module('docsTransclusionExample', [])
.controller('Controller', ['$scope', function($scope) {
  $scope.name = 'Tobias';
}])
.directive('myDialog', function() {
  return {
    restrict: 'E',
    transclude: true,
    scope: {},
    templateUrl: 'my-dialog.html',
    link: function(scope) {
      scope.name = 'Jeff';
    }
  };
});

index.html

<div ng-controller="Controller">
  <my-dialog>Check out the contents, {{name}}!</my-dialog>
</div>

my-dialog.html

<div class="alert" ng-transclude></div>

Skompilowane dane wyjściowe

<div ng-controller="Controller" class="ng-scope">
  <my-dialog class="ng-isolate-scope"><div class="alert" ng-transclude="">Check out the contents, Tobias!</div></my-dialog>
</div>

Transclude sprawia, że ​​treść dyrektywy z tą opcją ma dostęp do zakresu poza dyrektywą, a nie wewnątrz.

Ilustruje to poprzedni przykład. Zauważ, że dodaliśmy funkcję link w script.js, która redefiniuje nazwę jako Jeff. Zwykle spodziewalibyśmy się, że {{name}} to Jeff. Widzimy jednak w tym przykładzie, że powiązanie {{name}} to wciąż Tobiasz.

Najlepsza praktyka : używaj tylko transclude: truewtedy, gdy chcesz stworzyć dyrektywę, która otacza dowolne treści.

Arthur S.
źródło
0

transclude: true oznacza dodanie wszystkich elementów zdefiniowanych w dyrektywie do elementu szablonu dyrektywy.

if transclude: false te elementy nie są uwzględnione w końcowym pliku HTML dyrektywy, renderowany jest tylko szablon dyrektywy.

transclude: element oznacza, że ​​szablon dyrektywy nie jest używany, tylko element zdefiniowany w dyrektywie jest renderowany jako HTML.

kiedy definiujesz swoją dyrektywę, powinna ona być ograniczona do E, a kiedy dodajesz ją na stronie, wtedy

<my-directive><elements><my-directive>
<elements> is like <p>gratitude</p>
what i am talking about.
dev verma
źródło