W Angularze komponent jest specjalną dyrektywą, a jego cechą jest posiadanie własnego szablonu (html) i stylu (css). Dlatego użycie komponentów może uczynić nasz kod wysoce rozdzielonym, ponownego użytku i łatwego rozszerzenia. Zwykłe składniki definiuje się następująco:
demo.component.ts:
demo.component.html:
demo.component.scss:
Gdy odwołujemy się do komponentu, wygenerowana jest jego zawartość:
Załóżmy, że komponent musi akceptować treści projekcyjne z zewnątrz, co oznacza, że komponent prezentuje więcej niż tylko to, co definiuje. W tym momencie zaproszony jest główny bohater tego artykułung-content。
Prosta projekcja
Zacznijmy od najprostszego, dodajmy zmodyfikowany demo.component.html oraz demo.component.scss do demo.component.html, w następujący sposób:
demo.component.html:
demo.component.scss:
Dla efektu kolor tła pojemnika jest celowo definiowany jako pomarańczowy.
W tym momencie możemy przesyłać zawartość z zewnątrz, odwołując się do komponentu, a zawartość zewnętrzna będzie wyświetlana w pomarańczowym polu:
Projekcja celowana
Jeśli jest ich kilka jednocześnie, jak będą wyświetlane treści zewnętrzne?
Przyjrzyjmy się najpierw przykładowi, dla rozróżnienia dodałem niebieski obszar, zmodyfikowany demo.component.html oraz demo.component.scss w następujący sposób:
demo.component.html:
demo.component.scss:
Aby odnieść się do komponentu:
W tym momencie zobaczymy, że zawartość zewnętrzna jest wyświetlana na obszar niebieski:
Oczywiście, jeśli po niebieskim dodasz pomarańczowy numer kierunkowy, to zewnętrzna zawartość zostanie przeniesiona do pomarańczowego obszaru:
Z powyższego przykładu widzimy, że jeśli istnieje także proste , to zawartość zewnętrzna zostanie wyświetlona w ostatnim szablonie komponentu.
Znając ten problem, możemy się zastanawiać, czy możemy projektować treści zewnętrzne w sposób ukierunkowany? Odpowiedź brzmi oczywiście tak.
Aby sobie z tym poradzić, wesprzyj jednegowybraćAtrybuty, które pozwalają wyświetlać konkretne treści w określonym miejscu. Ta właściwość obsługuje selektory CSS (selektor tagów, selektor klas, selektor atrybutów、... ) do tego, czego chcesz. Jeśli na ng-content nie zostanie ustawiony żaden atrybut select, otrzyma pełną treść lub taką, która nie pasuje do żadnego innego elementu ng-content.
Patrząc bezpośrednio na przykład, zmodyfikowane demo.component.html i demo.component.scss wyglądają następująco:
demo.component.html:
demo.component.scss:
Jak widać w powyższym kodzie, niebieski obszar otrzyma część nagłówka tagu, czerwony obszar otrzyma część divu o klasie "demo2", zielony obszar otrzyma część divu o nazwie właściwości "demo3", a pomarańczowy obszar otrzyma resztę zewnętrznych treści (start, I am zawartość zewnętrznego osadzenia, koniec).
Aby odnieść się do komponentu:
W tym momencie zobaczymy zewnętrzną zawartość rzutowaną do określonego .
Poszerz wiedzę
ngProjectAs
Wiemy teraz, że właściwość select ng-content pozwala określić, że zawartość zewnętrzna jest rzutowana do danego .
Aby poprawnie projektować treść na podstawie atrybutu select, istnieje ograniczenie – niezależnie od tego, czy jest to nagłówek tagu, div o klasie "demo2", czy div o nazwie właściwości "demo3", wszystkie te tagi są bezpośrednimi podwęzłami tagu komponentu.
Co by się stało, gdyby nie bezpośredni subnode? Po prostu zmodyfikujmy kod odnoszący się do komponentu demo-component, umieścimy nagłówek tagu w div i zmodyfikujmy go w następujący sposób:
W tym momencie widzimy, że część treści z nagłówkiem zakładki nie jest już wyświetlana w niebieskim polu, lecz w pomarańczowym. Powodem jest to, że <ng-content select="header"></ng-content> nie może pasować do poprzedniego nagłówka tagu, więc ta część treści jest wyświetlana na <ng-content></ng-content> pomarańczowy obszar.
Aby rozwiązać ten problem, musimy użyć właściwości ngProjectAs, którą można zastosować do dowolnego elementu. Szczegóły są następujące:
Ustawiając właściwość ngProjectAs, div, w którym znajduje się nagłówek tagu, wskazuje select="header", a część nagłówka tagu jest rzutowana na niebieski obszar:
<ng-content>Nie "generuj" treści Zrób eksperyment Aby przeprowadzić eksperyment, najpierw zdefiniuj komponent demo-dziecko-komponent:
Komponent demo-komponent do:
Następnie w demo-component cast demo-child-component:
W tym momencie w konsoli widzimy, że inicjalizacja komponentu demo-child jest zakończona! Te słowa. Ale gdy klikamy przycisk przełączający operacje, inicjalizacja komponentu demo-child jest zakończona! Nie jest już drukowany, co oznacza, że nasz komponent demo-child jest instancjonowany tylko raz – nigdy nie niszczony ani odtwarzany.
Dlaczego tak się dzieje?
Przyczyny występowania
<ng-content> Nie "produkuje" treści, tylko wyświetla istniejące treści. Można to traktować jako równoważne z metodą node.appendChild(el) lub $(node).append(el) w jQuery: w tych metodach węzeł nie jest klonowany, lecz po prostu przenoszony do nowej lokalizacji. Dlatego cykl życia projektowanej treści będzie powiązany z miejscem, gdzie jest deklarowany, a nie wyświetlany na miejscu.
To również wyjaśnia poprzednie pytanie z zasady:Jeśli jest ich kilka jednocześnie, jak będą wyświetlane treści zewnętrzne?
Takie zachowanie wynika z dwóch powodów: spójności i wydajności. Co oznacza "pożądana spójność", że jako programista możesz zgadnąć zachowanie swojej aplikacji na podstawie jej kodu. Załóżmy, że napisałem następujący kod:
Oczywiście komponent demo-child-component zostanie zinstancjonowany raz, ale teraz, jeśli użyjemy komponentu z biblioteki firm trzecich:
Jeśli biblioteka firm trzecich ma kontrolę nad cyklem życia komponentu demo-child, nie będę miał sposobu, by wiedzieć, ile razy została zinstancjonowana. Jedynym sposobem jest przejrzenie kodu bibliotek firm trzecich, aby zrozumieć ich wewnętrzną logikę przetwarzania. Znaczenie powiązania cyklu życia komponentu z naszymi komponentami aplikacji zamiast z wrapperami polega na tym, że deweloperzy mogą kontrolować, czy liczniki są instancjonowane tylko raz, bez znajomości wewnętrznego kodu bibliotek firm trzecich.
Powody wydajnościjest ważniejsze. Ponieważ ng-content to tylko element ruchomy, można to robić w czasie kompilacji, a nie w czasie działania, co znacznie zmniejsza obciążenie faktycznej aplikacji.
Obejście
Aby komponent kontrolował instancję projekcyjnych podkomponentów, możemy to zrobić na dwa sposoby: używając <ng-template> elementów i ngTemplateOutlets wokół naszej treści lub stosując dyrektywy struktury z składnią "*". Dla uproszczenia użyjemy składni w przykładzie <ng-template> .
Komponent demo-komponent do:
Następnie włączamy demo-child-component do ng-template:
W tym momencie, gdy klikniemy przycisk przełączania, konsola wydrukujeInicjalizacja komponentu demo-child zakończona!Te słowa.
|