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) |