В 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 — содержимое внешнего встраивания, конец).
Для ссылки на компонент:
На этом этапе мы увидим, как внешний контент проецируется в указанный .
Расширяйте знания
ngProjectAs
Теперь мы знаем, что свойство select 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:
демо-компонент для:
Затем в демо-компоненте cast demo-child-component:
В этот момент в консоли мы видим, что инициализация демо-дочернего компонента завершена! Эти слова. Но когда мы нажимаем кнопку для переключения операций, инициализация демо-дочернего компонента завершена! Он больше не печатается, то есть компонент демо-дочернего компонента создаётся только один раз — никогда не уничтожается и не воссоздаётся.
Почему это происходит?
Причины возникновения
<ng-content> Он не «производит» контент, а просто проецирует существующий. Можно рассматривать его как эквивалент node.appendChild(el) или методу $(node).append(el) в jQuery: с этими методами узел не клонируется, а просто перемещается в новое место. Таким образом, жизненный цикл проектируемого контента будет привязан к месту объявления, а не к отображению на месте.
Это также объясняет предыдущий вопрос из принципа:Если их одновременно несколько, как будет проецироваться внешний контент?
Такое поведение происходит по двум причинам: последовательности и производительности. «Желаемая согласованность» означает, что как разработчик вы можете угадывать поведение своего приложения на основе его кода. Допустим, я написал следующий код:
Очевидно, что компонент demo-child-component будет создан один раз, но теперь, если использовать компонент из сторонней библиотеки:
Если сторонняя библиотека контролирует жизненный цикл компонента демо-дочернего компонента, я не смогу узнать, сколько раз он был создан. Единственный способ сделать это — изучить код сторонних библиотек, чтобы понять их внутреннюю логику обработки. Смысл привязки жизненного цикла компонента к нашим компонентам приложения, а не к обёрткам, заключается в том, что разработчики могут контролировать, чтобы счетчики создавались только один раз, не зная внутреннего кода сторонних библиотек.
Причины эффективностиважнее. Поскольку ng-контент — это просто движущийся элемент, его можно выполнять во время компиляции, а не во время выполнения, что значительно снижает нагрузку на реальное приложение.
Обходной путь
Чтобы компонент мог управлять инстанцией проектируемых подкомпонентов, мы можем сделать это двумя способами: используя <ng-template> элементы и ngTemplateOutlets вокруг нашего контента или используя структурные директивы с синтаксисом «*». Для простоты используем Syntax в <ng-template> примере .
демо-компонент для:
Затем включаем demo-child component в ng-шаблон:
В этот момент, когда мы нажимаем кнопку для переключения, консоль начинает печататьИнициализация демо-ребёнка-компонента завершена!Эти слова.
|