В Angular компонент є спеціальною директивою, і його особливість полягає в тому, що він має власний шаблон (html) і стиль (css). Тому використання компонентів може зробити наш код сильно роз'єднаним, багаторазовим і легко розширюваним. Звичайні компоненти визначаються наступним чином:
demo.component.ts:
demo.component.html:
demo.component.scss:
Коли ми посилаємося на компонент, його розборений вміст відображається:
Припустимо, що компонент має приймати зовнішній проєктований контент, що означає, що компонент зрештою показує більше, ніж просто те, що він визначає. У цей час запрошується головний герой цієї статтіng-контент。
Проста проєкція
Почнемо з найпростішого — додамо модифіковані demo.component.html та demo.component.scss до demo.component.html, наступним чином:
demo.component.html:
demo.component.scss:
Для ефекту фоновий колір контейнера навмисно визначений як помаранчевий.
На цьому етапі ми можемо транслювати контент ззовні при посиланні на компонент, і зовнішній контент відображатиметься в помаранчевій області:
Цільова проекція
Якщо їх одночасно кілька варіантів, як буде проєктуватися зовнішній контент?
Давайте спочатку розглянемо приклад: для різноманіття я додав синю область, модифікований demo.component.html та demo.component.scss наступним чином:
demo.component.html:
demo.component.scss:
Для посилання на компонент:
На цьому етапі ми побачимо, що зовнішній контент проектується в синю область:
Звісно, якщо поставити помаранчевий код після синього, зовнішній контент буде проєктований на помаранчеву область:
Отже, з наведеного вище прикладу ми бачимо, що якщо існує також простий , то зовнішній вміст буде проектуватися в останній шаблон компонента.
Тож, знаючи цю проблему, ми можемо замислитися: чи можемо ми цілеспрямовано проектувати зовнішній контент? Відповідь, очевидно, так.
Щоб впоратися з цим, підтримайте одногоВиберітьАтрибути, які дозволяють проектувати конкретний контент у певному місці. Ця властивість підтримує CSS-селектори (селектор тегів, селектор класів, селектор атрибутів、... ), щоб відповідати вашим бажанням. Якщо на ng-content не встановлено атрибут select, він отримає повний контент або той, що не відповідає жодному іншому елементу ng-content.
Якщо дивитися безпосередньо на приклад, модифіковані demo.component.html та demo.component.scss виглядають так:
demo.component.html:
demo.component.scss:
Як видно з наведеного вище коду, синя область отримає частину заголовка тега, червона — частину div з класом "demo2", зелена — частину div з назвою властивості "demo3", а помаранчева — решту зовнішнього контенту (start, I — вміст зовнішнього embed, кінець).
Для посилання на компонент:
На цьому етапі ми побачимо, як зовнішній контент проектується у заданий .
Розширити знання
ngProjectAs
Тепер ми знаємо, що властивість вибору ng-content дозволяє вказати, що зовнішній вміст проектується на заданий .
Щоб правильно проектувати контент на основі атрибута select, існує обмеження — чи то заголовок тега, div з класом "demo2", чи div з назвою властивості "demo3" — ці теги є прямими підвузлами компонентного тегу.
Що було б, якби не прямий підвузол? Давайте просто змінимо код, що посилається на компонент демо-компонента, помістимо заголовок тегів у div і змінимо його наступним чином:
На цьому етапі ми бачимо, що частина заголовка вкладки більше не проектується в синю область, а в помаранчеву область. Причина в тому, що <ng-content select="header"></ng-content> не може відповідати попередньому заголовку тегу, тому ця частина контенту проектується на <ng-content></ng-content> помаранчеву область.
Щоб розв'язати цю задачу, потрібно використати властивість ngProjectAs, яку можна застосувати до будь-якого елемента. Деталі такі:
Встановивши властивість ngProjectAs, div, де розташований заголовок тегу, вказує на select="header", а частина заголовка тегу проектується на синю область:
<ng-content>Не «генеруйте» контент Проведіть експеримент Для проведення експерименту спочатку визначимо компонент демо-дочірнього компонента:
демо-компонент для:
Потім у демо-компонентному касті демо-дитина-компонент:
На цьому етапі в консолі ми бачимо, що ініціалізація демо-дочірнього компонента завершена! Ці слова. Але коли ми натискаємо кнопку для перемикання операцій, ініціалізація demo-child-component завершена! Він більше не друкується, тобто компонент демо-дочірнього компонента створюється лише один раз — ніколи не знищується і не відтворюється.
Чому це відбувається?
Причини виникнення
<ng-content> Він не «створює» контент, а лише проектує вже існуючий. Ви можете уявити його як еквівалент методу node.appendChild(el) або методу $(node).append(el) у jQuery: у цих методах вузол не клонується, а просто переміщується на нове місце. Отже, життєвий цикл проєктованого контенту буде прив'язаний до місця, де він оголошено, а не відображається на місці.
Це також пояснює попереднє питання з принципу:Якщо їх одночасно кілька варіантів, як буде проєктуватися зовнішній контент?
Ця поведінка відбувається з двох причин: послідовність і продуктивність. Що означає «бажана послідовність» — це те, що як розробник ви можете здогадатися про поведінку свого додатка на основі його коду. Припустимо, я написав такий код:
Очевидно, що компонент demo-child-component буде створено один раз, але тепер, якщо ми використовуємо компонент із сторонньої бібліотеки:
Якщо стороння бібліотека контролює життєвий цикл компонента демо-дочірнього компонента, я не зможу знати, скільки разів він був створений. Єдиний спосіб зробити це — переглянути код сторонніх бібліотек, щоб зрозуміти їхню внутрішню логіку обробки. Сенс прив'язування життєвого циклу компонента до наших додаткових компонентів замість обгорток полягає в тому, що розробники можуть контролювати, щоб лічильники були створені лише один раз, не знаючи внутрішнього коду сторонніх бібліотек.
Причини продуктивностіважливіше. Оскільки ng-контент — це просто рухомий елемент, його можна виконувати під час компіляції, а не під час виконання, що суттєво зменшує навантаження на саму програму.
Обхідний шлях
Щоб компонент міг контролювати інстанцію проєктованих підкомпонентів, ми можемо зробити це двома способами: використовуючи <ng-template> елементи та ngTemplateOutlet навколо нашого контенту, або застосовуючи структурні директиви з синтаксисом "*". Для простоти ми використаємо Syntax у <ng-template> прикладі .
демо-компонент для:
Потім включаємо demo-child-component у ng-шаблон:
На цьому етапі, коли ми натискаємо кнопку для перемикання, консоль друкуєтьсяІніціалізація демо-дитинь-компонента завершена!Ці слова.
|