В 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 селектори (селектор на тагове, селектор на клас, селектор на атрибути、... ), за да отговаря на това, което искаш. Ако не е зададен select атрибут на ng-съдържанието, то ще получи цялото съдържание или съдържание, което не съвпада с друг ng-content елемент.
Гледайки директно примера, модифицираните demo.component.html и demo.component.scss са следните:
demo.component.html:
demo.component.scss:
Както виждате от горния код, синята зона ще получи частта от заглавието на тагова, червената зона ще получи частта от div с клас "demo2", зелената зона ще получи частта от div с името на свойството "demo3", а оранжевата зона ще получи останалото външно съдържание (start, I е съдържанието на външния embed, край).
За да се справим с компонента:
На този етап ще видим външното съдържание проектирано в зададения .
Разширяване на знанията
ngProjectAs
Сега знаем, че свойството select на ng-content ви позволява да зададете, че външното съдържание се проектира в дадено .
За правилно проектиране на съдържание въз основа на selecte атрибута има ограничение – независимо дали става дума за заглавие на тагове, div с клас "demo2" или div с име на свойство "demo3", тези тагове са директни подвъзли на компонентния таг.
Какво би станало, ако не беше директен подвъзел? Нека просто модифицираме кода, който препраща към компонента на демо-компонента, поставим заглавието на тагова в div и го модифицираме по следния начин:
В този момент виждаме, че заглавната част на съдържанието вече не се проектира в синята зона, а в оранжевата. Причината е, че <ng-content select="header"></ng-content> не може да съвпадне с предишния заглавие на тагова, затова тази част от съдържанието се проектира към <ng-content></ng-content> оранжевата област.
За да решим този проблем, трябва да използваме свойството ngProjectAs, което може да се приложи към всеки елемент. Подробностите са следните:
Чрез задаване на свойството ngProjectAs, div-ът, където се намира заглавието на тагова, сочи към select="header", а частта от заглавието на таго се проектира към синята област:
<ng-content>Не "генерирай" съдържание Направете експеримент За да направите експеримент, първо дефинирайте компонент демо-дете-компонент:
демо-компонент до:
След това в демо-компонент cast demo-child-component:
В този момент в конзолата виждаме, че инициализацията на демо-дете-компонент е завършена! Тези думи. Но когато натиснем бутона за смяна на операциите, инициализацията на демо-дете-компонент е завършена! Вече не се отпечатва, което означава, че нашият демо-детски компонент се създава само веднъж – никога не се унищожава и не възпроизвежда.
Защо се случва това?
Причини за появата
<ng-content> Той не "произвежда" съдържание, а просто проектира съществуващо съдържание. Можете да го разглеждате като еквивалент на node.appendChild(el) или метода $(node).append(el) в jQuery: при тези методи възелът не се клонира, а просто се премества на новото си местоположение. Следователно жизненият цикъл на проектираното съдържание ще бъде обвързан с мястото, където е декларирано, а не показвано на място.
Това също обяснява предишния въпрос от принципа:Ако има няколко едновременно, как ще се проектира външното съдържание?
Това поведение се случва по две причини: постоянство и представяне. "Желана консистентност" означава, че като разработчик можете да гадаете поведението на вашето приложение въз основа на кода му. Да кажем, че написах следния код:
Очевидно компонентът демо-дете-компонент ще бъде инстанциран веднъж, но сега, ако използваме компонент от библиотека на трета страна:
Ако библиотека на трета страна контролира жизнения цикъл на демо-детски компонент, няма да имам начин да знам колко пъти е бил инстанциран. Единственият начин да се постигне това е да се разгледа кода на библиотеки на трети страни, за да се разбере тяхната вътрешна логика на обработка. Смисълът на свързването на жизнения цикъл на компонент с нашите компоненти вместо с обвивките е, че разработчиците могат да контролират броячите да се инстанцират само веднъж, без да знаят вътрешния код на библиотеките на трети страни.
Причини за представянее по-важно. Тъй като ng-съдържанието е просто движещ се елемент, то може да се извършва по време на компилиране, а не по време на изпълнение, което значително намалява натоварването на самото приложение.
Заобиколно решение
За да може компонентът да контролира инстанцирането на проектираните подкомпоненти, можем да го направим по два начина: чрез <ng-template> използване на елементи и ngTemplateOutlets около нашето съдържание или чрез структурни директиви със синтаксис "*". За простота ще използваме Syntax в <ng-template> примера .
демо-компонент до:
След това включваме demo-child-component в ng-шаблона:
В този момент, когато натиснем бутона за смяна, конзолата ще се разпечатаИнициализацията на демо-дете-компонента е завършена!Тези думи.
|