Краткое руководство по основным понятиям в Angular

Angular — это фреймворк на основе TypeScript, разработанный Google, который используется для разработки веб-приложений и мобильных приложений. В этой статье мы рассмотрим некоторые основные концепции Angular, такие как Angular CLI, декораторы, хуки жизненного цикла, синтаксис шаблона и маршрутизация.

Угловой интерфейс командной строки

Angular предоставляет вам встроенный интерфейс командной строки, который позволяет очень легко и быстро настроить и запустить ваше приложение. Чтобы установить его, вам нужно установить менеджер пакетов узла.

npm install -g @angular/cli : эта команда поможет вам загрузить и установить последнюю версию интерфейса командной строки Angular с помощью npm. После установки Angular CLI вы можете использовать его с помощью команды ng.

ng help : эту команду можно использовать для просмотра всех доступных команд и их использования. Вы также можете увидеть использование и параметры для любой конкретной команды, используя ng command-name — help

ng doc keyword [options] : эта команда откроет официальную документацию по angular в браузере и выполнит поиск по ключевому слову, которое вы указали.

ng new app-name [options] : эта команда позволяет вам создать и инициализировать новое приложение angular, чтобы начать разработку.

ng add package-name [options] : эту команду можно использовать для добавления опубликованного пакета npm в рабочую область и настройки проекта для использования этой добавленной библиотеки.

ng generate schematic-name [options] : Эта команда помогает вам создавать/изменять файлы проекта в вашей текущей рабочей области на основе предоставленной вами схемы. Некоторые из наиболее часто используемых схем — application, module, class, component, service, directive, и pipe. Вы можете найти все схемы, которые вы можете использовать здесь.

ng serve project-name [options] : команда позволяет вам построить и запустить указанный проект в текущей рабочей области. При выполнении этой команды любые изменения, которые вы вносите в проект, автоматически перестраиваются и отображаются в браузере. Вы также можете использовать параметр --open or -o, чтобы открыть построенный проект непосредственно в браузере, и вы также можете добавить параметр --ssl, чтобы запустить его с использованием HTTPS.

ng build project-name [options] : эта команда создает указанный проект и создает выходные файлы в каталоге /dist. Содержимое этого каталога можно позже использовать для запуска вашего приложения с помощью нужного вам веб-сервера.

Декораторы

Декоратор в angular — это функция, которую мы используем для прикрепления метаданных к классу, методу, методу доступа, свойству или параметру. Мы применяем декоратор, используя знак @, за которым следует имя декоратора. В этом разделе мы обсудим различные типы декораторов.

@NgModule

Модуль Angular — это класс, помеченный декоратором @NgModule, который помогает настраивать и организовывать связанные вещи вместе. Он принимает объект метаданных, который идентифицирует собственные компоненты, директивы и каналы модуля, и вы также можете добавить поставщиков услуг в приложение. Мы можем сделать некоторые общедоступными через свойство exports, чтобы другие внешние компоненты могли их использовать.

@NgModule({
  declarations: [ AppComponent ],
  imports: [ BrowserModule ],
  exports: [ AppComponent ],
  providers: [ AppService ],
  bootstrap: [ AppComponent ]
})
export class AppModule {}

Ключ declarations — это список компонентов, директив и каналов, которые являются частью этого модуля.

Ключ imports — это список модулей, которые нужно импортировать в этот модуль.

Ключ exports — это список компонентов, директив и каналов, видимых внешним модулям, которые импортируют этот модуль.

Ключ providers — это список поставщиков внедрения зависимостей. Они видны как содержимому этого модуля, так и импортерам этого модуля.

@Компонент

@Componentобъявляет, что класс является компонентом. Он предоставляет метаданные о компоненте, такие как шаблон для ссылки, стили для ссылки, имя селектора, анимация, поставщики для использования, входы, выходы и т. д.

@Component({
  selector: 'demo',
  templateUrl: './demo.component.html',
  styleUrls: ['./demo.component.scss']
})
export class DemoComponent implements OnInit { }

@Директива

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

<demo *ngIf = "showDemo"/>

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

<demo [ngClass]="demoClasses"/>
<demo [ngStyle]="demoStyles"/>

@Инъекционный

@Injectable объявляет, что класс является поставщиком. Затем этот класс можно внедрить в другие компоненты в качестве поставщика.

@Injectable({
  providedIn: 'root'
})
export class DemoService { ... }

Здесь метаданные provideIn: ‘root’ означают, что служба доступна для всех компонентов приложения.

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

constructor(demoService: DemoService)

@Input и @Output

Декораторы @Input и @Output используются для объявления свойств, которые можно использовать для межкомпонентного взаимодействия. @Input используется для привязки свойства к внешнему компоненту.

Template of first component: <demo [myInput]="expression">
Second component: @Input() myInput: string;

@Output используется для привязки событий к внешнему компоненту.

Template of first component: <demo (myEvent)="eventName('hello')">
Second component: 
@Output() myEvent = new EventEmitter();
myEventName(value: string) {     
  this.myEvent.emit(value);   
}

И мы обсудим декораторы ввода и вывода более подробно в разделе о синтаксисе шаблонов.

@Труба

Декоратор @Pipe используется для объявления класса в виде конвейера. Он используется для преобразования данных с использованием встроенных или пользовательских каналов в шаблонах angular. Любой класс канала должен реализовывать интерфейс PipeTransform, и выражение передается в transform(). Этот метод обрабатывает логику преобразования данного выражения. Ниже вы можете увидеть пример встроенной трубы.

{{ demoExpression | uppercase }}

Крючки жизненного цикла

Экземпляр компонента/директивы имеет жизненный цикл, который начинается, когда angular создает экземпляр экземпляра и отображает представление этого компонента вместе с его дочерними представлениями. Жизненный цикл проходит через инициализацию и обнаружение изменений для изменений значений свойств, обновляет представления и экземпляр компонента и заканчивается, когда Angular уничтожает экземпляр и удаляет отображаемый шаблон из DOM.

  • ngOnChanges : это первый хук, который срабатывает в жизненном цикле, когда angular устанавливает или сбрасывает свойства экземпляра.
  • ngOnInit : вызывается, когда Angular инициализирует компонент/директиву после того, как он впервые установил и отобразил связанные входные свойства.
  • ngDoCheck : это срабатывает, когда вам нужно обнаружить изменения и отреагировать на них.
  • ngAfterContentInit : вызывается, когда Angular отправляет содержимое в представление компонента или в представление, в котором используется директива.
  • ngAfterViewInit : вызывается, когда Angular завершает инициализацию представлений компонента и дочерних представлений или представления, содержащего директиву.
  • ngOnDestroy : Это срабатывает непосредственно перед тем, как Angular уничтожит компонент/директиву. Этот хук можно использовать для окончательной очистки данных, отмены подписки на любые наблюдаемые объекты и отключения обработчиков событий во избежание утечек памяти.

Синтаксис шаблона

Интерполяция

Интерполяция позволяет встраивать выражения в текст разметки шаблона. В качестве разделителей используются двойные фигурные скобки {{ и }}.

Пример выражения, встроенного в шаблон с помощью интерполяции, показан ниже.

// variables in the component
currentUser = 'George'
currentProfile = 'assets/defaultIcon.png';
// template using interpolation
<h2> Current User: {{currentUser}} </h2>
<div><img alt="item" src="{{currentProfile}}"></div>

Здесь angular заменяет переменные currentUser и currentProfile строковыми значениями свойств соответствующего компонента. В этом случае значения будут George и assets/defaultIcon.png.

Заявления о шаблонах

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

Оператор шаблона появляется в кавычках справа от знака равенства =, например (event)="statement". Пример, показывающий, как использовать его в шаблоне, показан ниже.

<button type="button" (click)="deleteUser()">Delete User</button>

А синтаксический анализатор операторов шаблонов поддерживает как базовые присваивания (=), так и цепочки выражений с точкой с запятой (;) в кавычках.

Связывание

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

// property
<img [alt]="user.name" [src]="userImageUrl">
// event
<button type="button" (click)="onSave()">Save</button>
// two way
<input [(ngModel)]="name">
// attribute
<button type="button" [attr.aria-label]="help">help</button>
// class
<div [class.special]="isSpecial">Special</div>
// style
<button type="button" [style.color]="isSpecial ? 'red' : 'green'">

Директивы

Директивы используются для изменения поведения и структуры различных элементов шаблона. В широком смысле существует два вида директив: атрибутивные и структурные.

Директивы атрибутов

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

<div [ngClass]="isSpecial ? 'special' : ''">
  This div is special
</div>

В примере мы назначаем класс div на основе результата установки флага с помощью директивы ngClass.

// template
<div [ngStyle]="currentStyles">   
  This div is italic, normal weight, and extra large (24px). 
</div>
// component content
currentStyles: Record<string, string> = {};
this.currentStyles = {     
  'font-style': 'italic',
  'font-weight': 'normal',     
  'font-size': '24px'     
};

Здесь мы применяем набор стилей к div, передавая записи нескольких правил CSS с помощью директивы ngStyle.

<label for="example-ngModel">[(ngModel)]:</label> 
<input [(ngModel)]="currentItem.name" id="example-ngModel">
<input [ngModel]="currentItem.name (ngModelChange)="setUppercaseName($event)" id="example-uppercase">

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

Структурные директивы

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

<app-item-detail *ngIf="show" [item]="item"></app-item-detail>

Директива *ngIf может использоваться для отображения или скрытия компонента app-item-detail в шаблоне на основе результата флага show.

<div *ngFor="let item of items">{{item.name}}</div>

Директива *ngFor используется для перебора списка данных и создания шаблона на основе количества значений в списке. Здесь для каждого элемента мы создаем новый div с именем элемента.

<div [ngSwitch]="currentItem.feature">   
  <app-stout *ngSwitchCase="'stout'" [item]="currentItem"/>           
  
  <app-slim *ngSwitchCase="'slim'" [item]="currentItem"/>   
  
  <app-bright *ngSwitchCase="'bright'" [item]="currentItem"/>
  <app-unknown *ngSwitchDefault [item]="currentItem"/>
</div>

Здесь директива *ngSwitch используется, чтобы решить, какой компонент отображать в шаблоне, исходя из значения функции элемента.

Декораторы ввода и вывода

В сценариях, где нам нужно обмениваться данными между родительским и одним или несколькими дочерними компонентами, в игру вступают декораторы @Input и @Output.

Ввод

Чтобы передать данные от родителя к дочернему компоненту, мы используем декоратор @Input. Вы можете увидеть, как это работает, в приведенном ниже примере.

// child component
export class UserDetailsComponent {   
   @Input() username = ''; // decorate the property with @Input() 
}
// child template
<p> Logged in user: {{username}} </p>

Здесь вы можете видеть, что мы украшаем свойство, которое разрешает приток данных от родительского компонента к этому дочернему компоненту, с помощью декоратора @Input.

// parent component template 
<h2>Parent Component</h2>
<user-detail [username]="currentUser"></app-item-detail>
// parent component
export class ParentComponent {   
  currentUser = 'George'; 
}

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

Вывод

С другой стороны, чтобы передать данные из дочернего компонента в родительский, мы используем @Output decorator. Вы можете увидеть, как это работает, в приведенном ниже примере.

// child component
export class UserDetailComponent {    
  @Output() newUserEvent = new EventEmitter<string>();
  addNewUser(value: string) { 
    this.newUserEvent.emit(value);   
  } 
}
// child component's template
Add user:<input type="text" id="user-input" #newUser> 
<button type="button" (click)="addNewUser(newUser.value)">
  Add to parent's list
</button>

Здесь вы можете видеть, что мы связали декоратор @Output с событием click, чтобы вызвать событие, которое принимает метод с одним параметром.

// parent component
export class ParentComponent {   
  users = ['user1'];    
  addUser(newUser: string) {     
    this.users.push(newUser);   
  }
}
// parent component's template
<user-details (newUserEvent)="addUser($event)"></user-details>

Вы можете видеть, что событие, которое мы сопоставили для дочернего компонента, может использоваться для запуска addUser() родительского класса. И он передает данные события, настроенные в дочернем шаблоне, из поля ввода для добавления в список users в родительском компоненте.

Трубы

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

<p>The user's birthday is {{ birthday | date }}</p>

Маршрутизация

Угловая маршрутизация позволяет вам перемещаться между разными страницами в приложении. Чтобы использовать маршрутизацию в своем приложении, создайте приложение angular, используя дополнительную опцию, например ng new app-name --routing. Он сгенерирует AppRoutingModule, а также создаст массив для маршрутов в AppRoutingModule. Вы можете добавить маршруты для своего приложения в этот массив, как показано.

const routes: Routes = [   
  { path: 'component-one', component: FirstComponent },   
  { path: 'component-two', component: SecondComponent }, 
];

Теперь вы можете получить доступ к этим различным страницам в представлении, используя атрибут routerLink. Но сначала вам нужно добавить <router-outlet></router-outlet> в свой шаблон, именно здесь страницы навигации будут отображаться в представлении приложения. Ниже вы можете увидеть пример шаблона, в котором используются настроенные выше маршруты.

<ul>
  <li>
    <a routerLink="/component-one" routerLinkActive="active">
      First Page
    </a>
  </li>     
  <li>
    <a routerLink="/component-two" routerLinkActive="active">
      Second Page
    </a>
  </li>   
</ul>
<router-outlet></router-outlet>

routerLinkActive="active" добавит активный класс к ссылке, когда она активна.

Вы также можете перейти к различным маршрутам из вашего компонента. Вам нужно импортировать и внедрить Router в ваш компонент, как показано ниже.

constructor( private router: Router ) {}

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

this.router.navigate([‘/component-one’, { id: 1 }]);

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

Получение информации с маршрута

Вам нужно импортировать ActivatedRoute и ParamMap и внедрить ActivatedRoute в ваш компонент, где вы хотите прочитать информацию, как показано ниже.

constructor( private route: ActivatedRoute, ) {}

Вы можете обновить метод ngOnInit() в компоненте, чтобы получить доступ к ActivatedRoute и отслеживать нужный параметр, как показано.

ngOnInit() {
  /** 
   To access required and optional parameters specific to a route 
   eg: user/:paramOne  
  */
  this.route.paramMap.subscribe(params => {     
    this.myParameter = params.get('paramOne');   
  });
  /** 
   To access query parameters which are available to all routes 
   eg: user/one?id=1  
  */
  this.route.queryParams.subscribe(params => {     
    this.myParameter = params['id'];   
  });
}

Аутентификация маршрутов с помощью Guard

Вы можете использовать ng generate guard custom-guard для создания защиты для наших маршрутов. Затем вы можете использовать метод canActivate, чтобы иметь собственную логику для аутентификации, как показано.

export class CustomGuard implements CanActivate {   
  canActivate( 
     next: ActivatedRouteSnapshot, 
     state: RouterStateSnapshot) : boolean {       
        // custom authentication logic here 
  } 
}

После создания охранника вы можете использовать его со своим маршрутом, как показано на рисунке.

{   
  path: '/component-one',   
  component: FirstComponent,   
  canActivate: [CustomGuard] 
}

Это были некоторые из основных концепций Angular, надеюсь, вы нашли их полезными.

Спасибо за чтение, и счастливого обучения!

Если вам нравится читать подобные истории и вы хотите поддержать меня как писателя, подумайте о том, чтобы зарегистрироваться в качестве участника Medium. Это 5 долларов в месяц, что дает вам неограниченный доступ ко всем историям на Medium. Если вы зарегистрируетесь по моей ссылке, я получу небольшую комиссию.



Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter и LinkedIn. Посетите наш Community Discord и присоединитесь к нашему Коллективу талантов.