271 lines
28 KiB
Markdown
271 lines
28 KiB
Markdown
|
---
|
|||
|
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)
|