332 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			332 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | ||
| title: Directives
 | ||
| localeTitle: Директивы
 | ||
| ---
 | ||
| # Директивы
 | ||
| 
 | ||
| #### мотивация
 | ||
| 
 | ||
| Директивы являются основными для HTML-шаблона Angular. Наиболее значимым примером являются компоненты. Каждый вид компонента отображается ниже представления корневого компонента. Это может привести к созданию дерева представлений, определяющих одно приложение. Представление представляет собой класс ( `component.ts` ) и его шаблон ( `component.html` ).
 | ||
| 
 | ||
| Другие директивы, хотя и не столь важные, обеспечивают необходимую гибкость. Директива, расположенная на элементе, имеет полный контроль над ней. Использование `<ng-template></ng-template>` позволяет динамическое создание и удаление содержимого HTML. Microsyntax предоставляет разработчикам свободу дальнейшей настройки директивного поведения.
 | ||
| 
 | ||
| #### Директива
 | ||
| 
 | ||
| Директивы - это элементы и атрибуты компонентов, созданные и распознанные Angular. Угловое связывает элемент или атрибут с соответствующим определением класса. `@Directive` или `@Component` украшают эти классы. Оба индикатора указывают на Угловое, что класс выполняет в качестве директивы.
 | ||
| 
 | ||
| Некоторые директивы изменяют стиль элемента хоста. Другие директивы отображают представления или вставляют в существующие, как встроенные представления. Другими словами, они изменяют макет HTML.
 | ||
| 
 | ||
| В любом случае, директивы сигнализируют угловой компилятор. Они отмечают компоненты для модификации в зависимости от логики класса директивы.
 | ||
| 
 | ||
| #### Директива по компонентам
 | ||
| 
 | ||
| Директивы компонентов принципиально отличаются от других типов директив. Их обычно называют компонентами. Они образуют собственный уникальный тег HTML. Для каждого компонента существует некоторое количество HTML-шаблонов. Это не похоже на две другие директивы. Их классы - это чистая логика, работающая над тем, что предопределено в шаблоне HTML.
 | ||
| 
 | ||
| #### Создание компонентов
 | ||
| 
 | ||
| Создайте компонент с компонентом `ng generate component [name-of-component]` ; замените `[name-of-component]` на предпочтительное имя. Команда дает четыре разных файла, все они относятся к одному компоненту.
 | ||
| 
 | ||
| Компоненты `component.css` и `component.spec.ts` выходят за рамки данной статьи. В _директивном_ аспекте компонента участвуют два других файла. Взгляните на сгенерированные `component.ts` и `component.html` .
 | ||
| 
 | ||
| ```typescript
 | ||
| // example.component.ts 
 | ||
|  import { Component } from '@angular/core'; 
 | ||
|  
 | ||
|  @Component({ 
 | ||
|   selector: 'app-example', 
 | ||
|   templateUrl: './example.component.html' 
 | ||
|  }) 
 | ||
|  export class ExampleComponent { 
 | ||
|   constructor() { } 
 | ||
|  } 
 | ||
| ```
 | ||
| 
 | ||
| Несколько нерелевантных деталей были вырезаны из поколения по умолчанию `component.ts` . Таким образом, основное внимание уделяется самому компоненту.
 | ||
| 
 | ||
| ```html
 | ||
| 
 | ||
| <!-- example.component.html --> 
 | ||
|  
 | ||
|  <p>example works!</p> 
 | ||
| ```
 | ||
| 
 | ||
| Вставка ExampleComponent в качестве дочернего элемента другого компонента будет выглядеть следующим образом.
 | ||
| 
 | ||
| ```html
 | ||
| 
 | ||
| <!-- another.component.html --> 
 | ||
|  
 | ||
|  <h1>Welcome to AnotherComponent.</h1> 
 | ||
|  <h3>Check out ExampleComponent!</h3> 
 | ||
|  
 | ||
|  <!-- Outputs “<p>example works!</p>” --> 
 | ||
|  <app-example></app-example> 
 | ||
|  
 | ||
|  <h6>This is the end of the AnotherComponent template HTML.</h6> 
 | ||
| ```
 | ||
| 
 | ||
| Обратите внимание на `<app-example></app-example>` . `app-example` совпадает с селектором из декоратора @Component от `@Component` . Это директива компонента. Угловой распознает `app-example` и _направляет_ его визуализацию в класс ExampleComponent.
 | ||
| 
 | ||
| #### Структурная директива
 | ||
| 
 | ||
| Подумайте о том, являются `if` утверждения, `for` циклов и операторов `switch` в логике программирования. Эти логические конструкции определяют выполнение кода. Будет ли выполняться код ( `if` ), сколько раз он будет выполняться ( `for` ) и какой блок кода выполняется ( `switch` ).
 | ||
| 
 | ||
| Этот шаблон продолжает структурные директивы. Они определяют полученную структуру HTML шаблона. Они всегда связаны с использованием `ng-template` под капотом. `ng-template` предоставляет механизм для создания условно визуализированного HTML.
 | ||
| 
 | ||
| Вот три примера структурных директив. Каждый из них имеет логический аналог ( `if` , `for` , и `switch` ).
 | ||
| 
 | ||
| *   \* ngIf
 | ||
|     
 | ||
| *   \* ngFor
 | ||
|     
 | ||
| *   \* ngSwitchCase и \* ngSwitchDefault
 | ||
|     
 | ||
| 
 | ||
| **Важное примечание:** все три доступны через импорт `CommonModule` . Он доступен из `@angular/common` для импорта в корневом модуле приложения.
 | ||
| 
 | ||
| ##### \* ngIf
 | ||
| 
 | ||
| `*ngIf` проверяет заданное значение, чтобы проверить, является ли оно _правдивым_ или _ложным,_ основываясь на общей логической оценке в JavaScript. Если правдоподобно, появляется элемент и его innerHTML. В противном случае они никогда не будут отображаться в объектной модели домена (DOM).
 | ||
| 
 | ||
| ```html
 | ||
| 
 | ||
| <!-- renders “<h1>Hello!</h1>” --> 
 | ||
|  <div *ngIf="true"> 
 | ||
|   <h1>Hello!</h1> 
 | ||
|  </div> 
 | ||
|  
 | ||
|  <!-- does not render --> 
 | ||
|  <div *ngIf="false"> 
 | ||
|   <h1>Hi!</h1> 
 | ||
|  </div> 
 | ||
| ```
 | ||
| 
 | ||
| Это надуманный пример. Любое значение участника из класса компонента шаблона может быть заменено на `true` или `false` .
 | ||
| 
 | ||
| ПРИМЕЧАНИЕ. Вы также можете сделать следующее: \* ngIf, чтобы получить доступ к значению observalbe
 | ||
| 
 | ||
| ```html
 | ||
| 
 | ||
| <div *ngIf="observable$ | async as anyNameYouWant"> 
 | ||
|   {{  anyNameYouWant }} 
 | ||
|  </div> 
 | ||
| ```
 | ||
| 
 | ||
| ##### \* ngFor
 | ||
| 
 | ||
| `*ngFor` петли основаны на назначении с правой стороны, _микросинтактическом_ выражении. Микросинтакс выходит за рамки этой статьи. Знайте, что микросинтакс - это короткая форма логического выражения. Это происходит как одна строка, способная ссылаться на значения членов класса. Он может создавать повторяющиеся значения, что делает его полезным для `*ngFor` .
 | ||
| 
 | ||
| ```html
 | ||
| 
 | ||
| <ul> 
 | ||
|   <li *ngFor=“let potato of ['Russet', 'Sweet', 'Laura']; let i=index”> 
 | ||
|       Potato {{ i + 1 }}: {{ potato }} 
 | ||
|   </li> 
 | ||
|   <!-- Outputs 
 | ||
|   <li> 
 | ||
|       Potato 1: Russet 
 | ||
|   </li> 
 | ||
|   <li> 
 | ||
|       Potato 2: Sweet 
 | ||
|   </li> 
 | ||
|   <li> 
 | ||
|       Potato 3: Laura 
 | ||
|   </li> 
 | ||
|   --> 
 | ||
|  </ul> 
 | ||
| ```
 | ||
| 
 | ||
| `['Russet', 'Sweet', 'Laura']` является итерируемой величиной. Массивы являются одним из наиболее распространенных итераций. `*ngFor` выдает новый элемент `<li></li>` каждого элемента массива. Каждому элементу массива присваивается переменная `potato` . Все это делается с использованием микросинтекса. `*ngFor` определяет структурное содержание элемента `ul` . Это характерно для структурной директивы.
 | ||
| 
 | ||
| ПРИМЕЧАНИЕ. Вы также можете выполнить следующие действия с директивой \* ngFor, чтобы получить доступ к значению observalbe (хакерский)
 | ||
| 
 | ||
| ```html
 | ||
| 
 | ||
| <div *ngFor="let anyNameYouWant of [(observable$ | async)]"> 
 | ||
|   {{  anyNameYouWant }} 
 | ||
|  </div> 
 | ||
| ```
 | ||
| 
 | ||
| ##### \* ngSwitchCase и \* ngSwitchDefault
 | ||
| 
 | ||
| Эти две структурные директивы работают вместе, чтобы обеспечить функциональность `switch` для шаблона HTML.
 | ||
| 
 | ||
| ```html
 | ||
| 
 | ||
| <div [ngSwitch]=“potato”> 
 | ||
|   <h1 *ngSwitchCase=“'Russet'”>{{ potato }} is a Russet Potato.</h1> 
 | ||
|   <h1 *ngSwitchCase=“'Sweet'”>{{ potato }} is a Sweet Potato.</h1> 
 | ||
|   <h1 *ngSwitchCase=“'Laura'”>{{ potato }} is a Laura Potato.</h1> 
 | ||
|   <h1 *ngSwitchDefault>{{ potato }} is not a Russet, Sweet, nor Laura Potato.</h1> 
 | ||
|  </div> 
 | ||
| ```
 | ||
| 
 | ||
| Отображается только одно из выражений `*ngSwitch…` Обратите внимание на `[ngSwitch]` внутри элемента `div` переносит коммутатор. Это передает значение `potato` по `*ngSwitch...` Эта цепочка структурных директив определяет, какой элемент `h1` отображает.
 | ||
| 
 | ||
| Таким образом, `[ngSwitch]` не является структурной директивой, в отличие от `*ngSwitch…` Он передает значение, тогда как блок переключателя определяет окончательный формат HTML.
 | ||
| 
 | ||
| Помните, что стилизация и передача ценности не являются обязанностью структурных директив. Это касается директив атрибутов. Структурные директивы определяют только макет.
 | ||
| 
 | ||
| #### Создание структурной директивы [1](https://angular.io/guide/structural-directives)
 | ||
| 
 | ||
| В предыдущих примерах есть что-то важное. Все они обозначены звездочкой ( `*` ). `ng-template` используется под капотом при каждом применении звездочки.
 | ||
| 
 | ||
| `ng-template` определяет структурные директивы. В нем объясняется, как настроить HTML-шаблон для создания фактического HTML. Начните с создания директивы с директивой `ng generate directive [name-of-directive]` . Замените `[name-of-directive]` с предпочтительным именем. Команда дает следующее.
 | ||
| 
 | ||
| ```typescript
 | ||
| import { Directive } from '@angular/core'; 
 | ||
|  
 | ||
|  @Directive({ 
 | ||
|   selector: '[appExample]' 
 | ||
|  }) 
 | ||
|  export class ExampleDirective { 
 | ||
|   constructor() { } 
 | ||
|  } 
 | ||
| ```
 | ||
| 
 | ||
| Этот директивный скелет довольно голый. Он еще не знает, строим ли мы конструктивную или атрибутивную директиву. `selector: '[appExample]'` сообщает Angular о том, к какому атрибуту относится карта. Поскольку вы создаете структурную директиву, измените скелет следующим образом.
 | ||
| 
 | ||
| ```typescript
 | ||
| Import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; 
 | ||
|  
 | ||
|  @Directive({ 
 | ||
|   selector: '[appExample]' 
 | ||
|  }) 
 | ||
|  export class ExampleDirective { 
 | ||
|   @Input() set appExample(booleanValue: boolean) { 
 | ||
|       if (booleanValue) { 
 | ||
|           this.ngTemplate.createEmbeddedView(this.innerHTMLOfTemplateScope); 
 | ||
|       } 
 | ||
|       else { 
 | ||
|           this.ngTemplate.clear(); 
 | ||
|       } 
 | ||
|   } 
 | ||
|  
 | ||
|   constructor( 
 | ||
|       private innerHTMLOfTemplateScope:TemplateRef<any>, 
 | ||
|       private ngTemplate:ViewContainerRef 
 | ||
|   ) { } 
 | ||
|  } 
 | ||
| ```
 | ||
| 
 | ||
| Хорошим примером является включение произвольного элемента с атрибутом `appExample` .
 | ||
| 
 | ||
| ```html
 | ||
| 
 | ||
| <div *appExample=“value”>innerHTML content</div> 
 | ||
|  <!-- This is shorthand for: 
 | ||
|  <ng-template> 
 | ||
|   <div>innerHTML content</div> 
 | ||
|  </ng-template> 
 | ||
|  --> 
 | ||
| ```
 | ||
| 
 | ||
| Это очень много. `@Input() set ...` является объявлением члена setter. Он выполняется всякий раз, когда атрибут `appExample` появляется внутри элемента и ему присваивается логическое значение. Функция setter получает это логическое значение в качестве своего параметра для выполнения.
 | ||
| 
 | ||
| `TemplateRef<any>` ссылается на innerHTML `<ng-template></ng-template>` . Звездочка, используемая в предыдущих примерах, является сокращением комментария в вышеуказанном блоке кода. `ng-template` действует как _секретный соус_ для его структурных директив.
 | ||
| 
 | ||
| `ViewContainerRef` ссылается на область инкапсуляции `<ng-template></ng-template>` . `ng-template` не является фактическим элементом. Это маркер для компилятора Angular, который в итоге получает комментарии.
 | ||
| 
 | ||
| `ViewContainerRef` имеет два метода: `clear()` и `createEmbeddedView()` . Вы можете думать о встроенных представлениях как о HTML, помещенных в элемент `ng-template` .
 | ||
| 
 | ||
| `clear()` удаляет все существующие HTML-области в пределах `ng-template` с HTML-дисплея. `createEmbeddedView()` нацелен на HTML внутри `ng-template` как отображаемый HTML.
 | ||
| 
 | ||
| Если вы понимаете последний пример кода, то у вас есть `*ngIf` понимание `*ngIf` , `*ngFor` , `*ngSwitchCase` и `*ngSwitchDefault` . Все они определяют макет со ссылкой на `TemplateRef<any>` и `ViewContainerRef` .
 | ||
| 
 | ||
| Фактически, ExampleDirective выше имитирует функциональность `*ngIf` !
 | ||
| 
 | ||
| ```html
 | ||
| 
 | ||
| <!-- renders “<h1>Hello!</h1>” --> 
 | ||
|  <div *ngExample="true"> 
 | ||
|   <h1>Hello!</h1> 
 | ||
|  </div> 
 | ||
|  
 | ||
|  <!-- does not render --> 
 | ||
|  <div *appExample="false"> 
 | ||
|   <h1>Hi!</h1> 
 | ||
|  </div> 
 | ||
| ```
 | ||
| 
 | ||
| Никогда не забывайте звездочку ( `*` ). Это стенограмма элемента `ng-template` который ссылается на наш класс директив.
 | ||
| 
 | ||
| #### Директива по атрибутам
 | ||
| 
 | ||
| Директивы атрибутов похожи на структурные. Кроме того, директивы атрибутов имеют нулевой эффект на макете HTML. Они не реализуют `<ng-template></ng-template>` . Это атрибуты, которые ссылаются на свой элемент хоста для стилистических изменений.
 | ||
| 
 | ||
| Пример лучше всего объясняет их цель.
 | ||
| 
 | ||
| #### Создание директивы атрибутов [2](https://angular.io/guide/attribute-directives)
 | ||
| 
 | ||
| Создайте еще одну директиву: `ng generate directive [name-of-directive]` . Замените `[name-of-directive]` с предпочтительным именем.
 | ||
| 
 | ||
| ```typescript
 | ||
| import { Directive } from '@angular/core'; 
 | ||
|  
 | ||
|  @Directive({ 
 | ||
|   selector: '[appExample]' 
 | ||
|  }) 
 | ||
|  export class ExampleDirective { 
 | ||
|   constructor() { } 
 | ||
|  } 
 | ||
| ```
 | ||
| 
 | ||
| Атрибуты и структурные директивы начинаются с того же скелета. Еще несколько дополнений будут отличаться от директивы атрибута.
 | ||
| 
 | ||
| ```typescript
 | ||
| import { Directive, Input, ElementRef } from '@angular/core'; 
 | ||
|  
 | ||
|  @Directive({ 
 | ||
|   selector: '[appExample]' 
 | ||
|  }) 
 | ||
|  export class ExampleDirective { 
 | ||
|   @Input() set appExample(color:string) { 
 | ||
|       this.host.nativeElement.style.color = color; 
 | ||
|   } 
 | ||
|  
 | ||
|   constructor(private host:ElementRef) { } 
 | ||
|  } 
 | ||
| ```
 | ||
| 
 | ||
| Несколько элементов для тестирования помогут.
 | ||
| 
 | ||
| ```html
 | ||
| 
 | ||
| <!-- the intended results are self-explanatory --> 
 | ||
|  <div appExample=“purple”>This text is purple!</div> 
 | ||
|  <div appExample=“blue”>This text is blue!</div> 
 | ||
|  <div appExample=“red”>This text is red!</div> 
 | ||
| ```
 | ||
| 
 | ||
| `ElementRef` предоставляет прямую ссылку на элемент хоста. `ElementRef.nativeElement` захватывает узел DOM. С узлом, `this.host.nativeElement.style.color = color` компонента так же проста, как `this.host.nativeElement.style.color = color` .
 | ||
| 
 | ||
| `@Input() set ...` - это еще одна функция setter, которая считывает значение, которое она назначается при ее реализации как атрибут. Он переназначает свойство цвета таблицы стилей каждого элемента.
 | ||
| 
 | ||
| #### Вывод
 | ||
| 
 | ||
| Директивы - это мощный инструмент, доступный в HTML-шаблоне Angular. Это то, как компоненты соединяются друг с другом. Внутри каждого компонента они обеспечивают средство стиля и макета.
 | ||
| 
 | ||
| Существует много других вариантов построения каждого типа директивы. К сожалению, для каждого из них слишком много для одной статьи. Достаточно простого понимания директив, чтобы продвигаться вперед с более продвинутыми ресурсами.
 | ||
| 
 | ||
| Проверьте нижние ресурсы, чтобы погрузиться глубже. Существуют ссылки для каждого типа директивы. Каждая ссылка является частью той же документации, поэтому нет необходимости возвращаться сюда после посещения первой ссылки!
 | ||
| 
 | ||
| ## источники
 | ||
| 
 | ||
| 1.  [Угловая команда. _Структурные директивы_ . Google. Доступ к 28 мая 2018 года](https://angular.io/guide/structural-directives)
 | ||
|     
 | ||
| 2.  [Угловая команда. _Директивы атрибутов_ . Google. Доступ к 28 мая 2018 года](https://angular.io/guide/attribute-directives)
 | ||
|     
 | ||
| 
 | ||
| ## Ресурсы
 | ||
| 
 | ||
| *   [Угловая документация](https://angular.io/guide/pipes)
 | ||
|     
 | ||
| *   [Угловой репозиторий GitHub](https://github.com/angular/angular)
 | ||
|     
 | ||
| *   [Угловые компоненты](https://angular.io/guide/architecture-components)
 | ||
|     
 | ||
| *   [Угловые структурные директивы](https://angular.io/guide/structural-directives)
 | ||
|     
 | ||
| *   [Угловые атрибуты](https://angular.io/guide/attribute-directives)
 | ||
|     
 | ||
| *   [Угловая CLI](https://cli.angular.io) |