---
title: Components
localeTitle: Компоненты
---
# Компоненты

#### мотивация

Угловое содержит множество _схем_ для создания приложений. Компоненты - одна из таких схем. Они охватывают единую логику, связанную с одной частью приложения. Компоненты часто взаимодействуют с другими схемами для более эффективной работы.

Среди всех схем компоненты обычно потребляют больше, чем обеспечивают. В то время как другие схемы, такие как директивы, трубы и службы, предлагают утилиту, компоненты используют. Они отвечают за интерфейс приложения, поэтому имеет смысл, почему утилита потребления.

Компоненты упрощают применение. Логика перемотки в единую секцию видимого интерфейса является их основной целью. Чтобы поэтапно создавать приложения, вы должны создавать поэтапные компоненты. Компоненты выступают в качестве блоков Angular в конце концов.

#### Компоненты Введение

Как уже упоминалось, компоненты потребляют утилиту (услуги / ресурсы). Они стоят между бизнес-логикой и презентацией, чтобы создать единую единицу. Угловой придает каждому механизму различные механизмы. Эти вложения определяют класс как компонент и определяют его стандартные возможности.

Угловые должны распознавать компоненты, когда они сталкиваются с ними. Для этого `@Component` должен украсить каждый класс, который должен быть компонентом. Декораторы показывают Угловое, что такое класс.

В случае компонента он должен знать, как взаимодействовать с его инжектором, подключаться к шаблону, извлекать из списка стилей, инкапсулировать его стили и т. Д. Угловые заботятся о большинстве требований низкого уровня. Разработчикам по-прежнему необходимо настроить поведение компонента, импортировать его зависимости и расширить свою логику.

Для всех таких вещей у нас есть класс компонента. Класс сохраняет все относительно однородным. Он инкапсулирует бизнес-логику компонента.

#### Компонентный класс и метаданные

Идем дальше и устанавливаем [Угловой интерфейс командной строки (CLI)](https://cli.angular.io) . Вы можете узнать больше об этом из [этой статьи](https://guide.freecodecamp.org/angular/command-line-interface) . Команда CLI `ng generate component [name-of-component]` дает следующее.

```typescript
import { Component, OnInit } from '@angular/core'; 
 
 @Component({ 
  selector: 'app-example', 
  templateUrl: './example.component.html', 
  styleUrls: ['./example.component.css'] 
 }) 
 export class ExampleComponent implements OnInit { 
  constructor() { } 
 
  ngOnInit() { } 
 } 
```

Это основной скелет, из которого происходят все большие компоненты. Декоратором `@Component` является наиболее важная часть. Без него приведенный выше пример становится универсальным классом. Угловые полагаются на декораторов, чтобы различать тип схемы.

`@Component` получает метаданные как один объект. Декораторы - это просто функции JavaScript под капотом. Они принимают аргументы как с объектом метаданных. Объект метаданных настраивает базовые зависимости компонента. Каждая область играет определенную роль.

*   `selector:` указывает, что Angular связывает компонент с определенным элементом в HTML-шаблоне приложения.
    
*   `templateUrl:` принимает расположение файла HTML-кода компонента (здесь отображаются данные).
    
*   `styleUrls:` принимает массив расположения файлов стилей (строк). Эти таблицы стилей предназначены для заданного шаблона компонента.
    

Подумайте о метаданных как о большой конфигурации конфигурации. Декоратор принимает его так, чтобы он мог генерировать данные, специфичные для этого компонента. Декоратор _украшает_ базовый класс данными, необходимыми для поведения его класса. Класс _компонента,_ который есть.

Экспорт подписей класса по умолчанию позволяет импортировать компонент. `ngOnInit` также реализуется. `implements` команду определять определенные методы для определения интерфейса. `ngOnInit` - это крючок жизненного цикла.

#### Обнаружение жизненного цикла компонентов и их изменение

Компоненты используют всевозможные инструменты, услуги и функции. Ключевой функцией, доступной для компонентов, является привязка к жизненному циклу. Объяснение для каждого крючка существует [в этой статье](https://guide.freecodecamp.org/angular/lifecycle-hooks) .

Всего восемь, и все они выполняют функцию синхронизации. Они выполняются условно, поскольку компонент переходит из состояния в состояние посредством [обнаружения изменений](https://blog.angularindepth.com/everything-you-need-to-know-about-change-detection-in-angular-8006c51d206f) . Этот процесс происходит постоянно в дереве компонентов. Он ищет изменения в данных, которые заслуживают повторного рендеринга шаблона.

Время двигаться дальше. Более подробную информацию о жизненном цикле компонентов см. В вышеупомянутых статьях. Это заслуживает гораздо большего объяснения.

#### Компонентные данные

Данные управляют всем. Компоненты не являются исключением. Компоненты инкапсулируют все свои данные. Чтобы получать данные извне, компонент должен явно объявить его. Эта форма конфиденциальности ведет к сбою информации в дереве компонентов.

Данные определяют, что отображается из класса компонента в его шаблон. Любые обновления данных класса будут (или, по крайней мере, должны) обновлять отображение шаблона.

Компоненты часто инициализируют набор элементов (или переменных), которые хранят данные. Они используются во всей логике класса компонентов для удобства. Эта информация подпитывает логику, приводящую к шаблону и его поведению. См. Следующий пример.

```typescript
// ./components/example/example.component.ts 
 
 import { Component, OnInit } from '@angular/core'; 
 import { Post, DATA } from '../../data/posts.data'; 
 
 @Component({ 
  selector: 'app-example', 
  templateUrl: './example.component.html' 
 }) 
 export class ExampleComponent implements OnInit { 
  username: string; 
  totalPosts: number; 
  allPosts: Post[]; 
 
  deletePost(index: number): void { 
    this.allPosts.splice(index, 1); 
    this.totalPosts = this.allPosts.length; 
  } 
 
  ngOnInit(): void { 
    this.username = DATA.author; 
    this.totalPosts = DATA.thePosts.length; 
    this.allPosts = DATA.thePosts; 
  } 
 } 
```

```html

<!-- ./components/example/example.component.html --> 
 
 <h1>{{ username }}</h1> 
 <span>Change Name: </span><input [(ngModel)]="username"> 
 <h3>Posts: {{ totalPosts }}</h3> 
 <ul> 
 <hr/> 
 <div *ngFor="let post of allPosts; let i=index"> 
  <button (click)="deletePost(i)">DELETE</button> 
  <h6>{{ post.title }}</h6> 
  <p>{{ post.body }}</p> 
  <hr/> 
 </div> 
 </ul> 
```

Обратите внимание на то, как компонент взаимодействует со своими данными. Сначала он извлекает его из `../../data/posts.data` прежде чем он начнет пересылать его в шаблон для отображения.

Данные отображаются по всему шаблону. Внутри двойных фигурных скобок значение переменной отображается из класса компонента в фигурные скобки. `*ngFor` в `allPosts` классов `allPosts` . Нажатие на кнопку удаляет определенный элемент из `allPosts` по его индексу. Вы даже можете изменить самое верхнее `username` , введя его в поле ввода.

Вышеупомянутые взаимодействия изменяют данные класса компонента, которые, в свою очередь, обновляют HTML-код компонента. Компоненты обеспечивают базовую логику, которая облегчает поток данных. Шаблон HTML делает эти данные доступными для пользователя.

#### Шаблон компонента

В предыдущем примере шаблона HTML был показан интересный синтаксис. Синтаксис не был фактическим HTML. Это HTML-шаблон Angular. Некоторые часто ссылаются на то, что HTML _Plus_ распознается только компилятором Angular. Компилятор поддерживает синтаксис, приводящий к динамической обработке HTML. Эта статья будет часто ссылаться на нее как «шаблон HTML» или «шаблон».

Синтаксис позволяет компонентам вводить данные непосредственно в HTML-шаблон. Инъекция является динамичной. Смысл, данные могут выполнять итерацию и отображать себя как HTML без внешней помощи. Угловой компилятор компилирует его в настоящий HTML к моменту, когда он достигнет веб-браузера.

Чтобы узнать больше о некоторых способах [привязки](https://guide.freecodecamp.org/angular/data-binding) данных к шаблону, прочитайте о [привязке данных в Angular](https://guide.freecodecamp.org/angular/data-binding) . Несколько примеров привязки данных произошли в предыдущем примере ( `{{ ... }}` ). Для этой статьи достаточно распознать взаимодействие данных между классом компонента и его шаблоном.

#### Запрос шаблона

Данные, управляющие состоянием шаблона, действуют нормально. Тем не менее, чистые данные не всегда удовлетворяют предполагаемому дизайну приложения. Может потребоваться взаимодействие с объектной моделью документа (DOM).

Для этого компонент должен иметь ссылку на элементы шаблона. Когда данные изменяются, компонент может манипулировать DOM явно. Это более декларативный подход.

Компоненты могут захватывать ссылки, используя интерфейс прикладного программирования DOM веб-браузера (API). Плохая идея. Угловые предпочитают кросс-платформенную совместимость. Чтобы компонент работал вне веб-браузера, ему нужно использовать API-интерфейс Angular, а не DOM.

Компоненты могут запрашивать свои шаблоны с помощью декораторов `@ViewChild` и `ContentChild` . Они захватывают ссылки на элементы шаблона от имени класса компонента.

```typescript
import { Component, ViewChild, ContentChild, ElementRef, Renderer2, AfterContentChecked, AfterViewChecked } from '@angular/core'; 
 
 @Component({ 
  selector: 'app-child', 
  template: ` 
  <button (click)="toggleEnlarge()">Toggle Enlarge</button> 
  <ng-content></ng-content> 
  ` 
 }) 
 export class ChildComponent implements AfterContentChecked { 
  @ContentChild("pReference", { read: ElementRef }) pElement: ElementRef; 
  textEnlarge: boolean = false; 
 
  constructor(private renderer: Renderer2) { } 
 
  toggleEnlarge() { 
    this.textEnlarge = !this.textEnlarge; 
  } 
 
  ngAfterContentChecked() { 
    if (this.textEnlarge) 
      this.renderer.setStyle(this.pElement.nativeElement, 'font-size', '25px'); 
      else 
      this.renderer.setStyle(this.pElement.nativeElement, 'font-size', 'initial'); 
    } 
 } 
 
 @Component({ 
  selector: 'app-parent', 
  template: ` 
  <button (click)="toggleHighlight()">Toggle Highlight</button> 
  <h1 #hOneRefereance>View Child</h1> 
  <app-child> 
    <p #pReference>Content Child</p> 
  </app-child> 
  ` 
 }) 
 export class ParentComponent implements AfterViewChecked { 
  @ViewChild("hOneRefereance", { read: ElementRef }) hOneElement: ElementRef; 
  textHighlight: boolean = false; 
 
  constructor(private renderer: Renderer2) { } 
 
  toggleHighlight() { 
    this.textHighlight = !this.textHighlight; 
  } 
 
  ngAfterViewChecked() { 
    if (this.textHighlight) 
      this.renderer.setStyle(this.hOneElement.nativeElement, 'background-color', 'yellow'); 
    else 
      this.renderer.setStyle(this.hOneElement.nativeElement, 'background-color', 'initial'); 
  } 
 } 
```

Вышеприведенный пример содержит две кнопки, которые переключают определенный стиль для каждого элемента. Нажатие на кнопки переключает значения true / false, уникальные для каждого компонента. Эти логические значения определяют, применяются ли пользовательские стили. Вместо этих значений, которые `ngAfterViewChecked` изменения, крючки жизненного цикла ( `ngAfterViewChecked` и `ngAfterContentChecked` ) декларативно изменяют DOM.

В декларативном подходе явно изменяется стиль с помощью ссылки на элемент. При императивном программировании изменения в данных DOM, основанных на данных, являются неявными. Ознакомьтесь с этой статьей по [обязательному и декларативному программированию,](https://codeburst.io/declarative-vs-imperative-programming-a8a7c93d9ad2) чтобы узнать больше.

Главное отметить, как эти ссылки извлекаются из шаблона. В этом примере два раздела шаблона задаются с использованием двух декораторов: `@ViewChild` и `@ContentChild` .

Они отличаются тем, что они ищут ссылку на элемент, будь то в DOM содержимого или вид DOM. Эти два DOM существуют в шаблоне ParentComponent. Дифференциация между ними важна, потому что они заканчивают рендеринг в разное время.

Вот почему существуют `@ViewChild` и `@ContentChild` . Они работают вместе со своими спутниками жизненного цикла `ngAfterViewChecked` и `ngAfterContentChecked` . Эти крючки жизненного цикла ждут, пока их соответствующие запросы будут разрешены до выполнения.

После устранения `@ViewChild` и `@ContentChild` предоставляют ссылки на два элемента. Оба они существуют в отдельных частях DOM. Булевские данные все еще определяют результат. Как этот результат переводится в DOM, это ключевое отличие от предыдущего. DOM обновляется с помощью прямой обработки `Renderer2` .

#### Контентная проекция

Содержимое DOM существует во внутреннемHTML элемента `<app-child></app-child>` ChildComponent. Все это расположено в шаблоне ParentComponent. InnerHTML из `app-child` _проектов_ на шаблон ChildComponent через `<ng-content></ng-content>` .

Это иллюстрирует проецирование контента. Отображение содержимого из `one` компонента в другой с помощью innerHTML `another` тегов в `one` шаблоне, чтобы `another` компонент мог вытащить этот внутреннийHTML в свой собственный шаблон через `<ng-content></ng-content>` . _Спасибо, что прочитали это предложение._

Следовательно, почему ChildComponent ссылается на элемент `<p></p>` используя `@ContentChild` . Содержимое, содержащееся в `<app-child></app-child>` в шаблоне ParentComponent, составляет содержание DOM. ChildComponent ссылается на элемент с запросом `@ContentChild` .

Представление ParentComponent DOM состоит из всего доступного изнутри представления компонента. Это необязательно включает весь шаблон, заданный innerHTML `<app-child></app-child>` . Опять же, эта часть DOM запрашивается у ChildComponent с помощью `@ContentChild` . Все остальное запрашивается с помощью `@ViewChild` из класса `@ViewChild` .

Это отличный способ для компонентов обмениваться контентом и запрашивать его собственный контент независимо от его типа DOM. Компоненты могут связываться с самим собой и другими, используя также привязку данных. Подробнее об этом читайте в [этой статье](https://guide.freecodecamp.org/angular/data-binding) .

#### Стили компонентов

Стили имеют решающее значение для удобочитаемости и интерактивности компонента. Каждый компонент инкапсулирует свои зависимости в стиле. Таким образом, они применяются только к HTML-шаблону компонента. Специальная техника, созданная теневым DOM HTML, делает это возможным.

Теневая ветвь DOM может существовать на любом элементе. Эта часть DOM не может быть замечена из исходного кода HTML. Стандартные HTML-элементы используют теневую DOM для предоставления своих торговых марок. Теневая ветка DOM должна привязываться к видимому компоненту, чтобы он мог стилизовать и настроить его.

Уникальный аспект о ветке теневой DOM - это его инкапсуляция. Все, что используется для создания элемента корня теневого дерева DOM, принадлежит ему. Ни один другой элемент не может получить к нему доступ.

Угловая охватывает эту форму инкапсуляции компонентами. Элемент стиля и шаблон компонента инкапсулируются вместе. Никакие другие компоненты не имеют к ним доступа. Столкновения стилей не могут возникнуть.

Угловой не использует тени DOM по умолчанию. Он использует систему эмуляции, которая имитирует поведение теневого DOM. Это временная мера, поскольку некоторые веб-браузеры еще не поддерживают теневой API DOM.

Метаданные `@Component` содержат поле `encapsulation` . Это позволяет разработчикам переключаться между emulated shadow DOM, реальной теневой DOM или нет. Вот варианты в соответствующем порядке:

*   `ViewEncapsulation.Emulated` - поддельная тень DOM (по умолчанию)
    
*   `ViewEncapsulation.Native` - реальная теневая DOM (теперь устаревшая с Angular 6.0.8)
    
*   `ViewEncapsulation.None` - ни
    

`ViewEncapsulation.None` означает, что листы стиля компонента поднимаются в глобальную область. Не рекомендуется рассматривать компоненты, которые должны составлять их собственное частное устройство (инкапсуляция). Угловая по-прежнему обеспечивает ее как спасательный люк для экстремальных ситуаций.

#### Вывод

Компоненты создают приложения. Они индивидуально ограничены и раздельны друг от друга, если они не установлены иным образом. Приложения обычно начинаются с корневого модуля. В прошлом компоненты составляли удлиненное дерево, определяющее остальную часть приложения.

Компоненты охватывают обозначенный блок интерфейса приложения. Это включает в себя стили, логику и макет. Другие схемы, такие как трубы, службы и директивы, часто используются в коде компонента. Вы можете узнать больше об этих взаимодействиях в некоторых других статьях с угловым руководством.

Не забывайте, что компоненты должны [загружаться](https://angular.io/guide/bootstrapping) . Это может произойти в корневом модуле или метаданных компонента. Это так Угловое распознает компонент везде, где он появляется в приложении.

Вы всегда можете узнать больше, изучая приведенные ниже ссылки. Компонент имеет гораздо большую глубину, чем то, что может передать эта статья.

## источники

*   [Угловая команда. «Угловые документы». _Google_ . Доступ к 3 июня 2018 года](https://angular.io/guide)
*   [Сообщество Mozilla MDN. «Использование Shadow DOM». _Mozilla_ , обновленный 30 мая 2018 года. Доступ к 3 июня 2018 года](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM)
*   [Манди, Ян. «Декларативное и императивное программирование». _codeburst.io_ , 20 февраля 2017. Получено 3 июня 2018 года](https://codeburst.io/declarative-vs-imperative-programming-a8a7c93d9ad2)

## Ресурсы

*   [Угловая документация](https://angular.io/guide)
*   [Угловой репозиторий GitHub](https://github.com/angular/angular)
*   [Введение в компоненты](https://angular.io/guide/architecture-components)
*   [Компоненты глубины](https://angular.io/guide/displaying-data)
*   [Тень DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM)