Как работает привязка данных (data binding) в Angular?
Привязка данных (data binding) в Angular — это механизм синхронизации данных между компонентом и шаблоном. Angular предоставляет несколько видов привязки, каждый из которых подходит для разных сценариев взаимодействия между логикой и представлением. Привязка позволяет динамически отображать данные, реагировать на события и связывать формы с моделью.
1. Типы привязки данных в Angular
Angular поддерживает четыре основных типа привязки данных:
1.1. Интерполяция (Interpolation)
Синтаксис: {{ выражение }}
Позволяет вставлять значения переменных из компонента в HTML.
Пример:
export class AppComponent {
title = 'Привет, Angular!';
}
<h1>{{ title }}</h1>
-
Работает только на чтение;
-
Может включать выражения: {{ title.toUpperCase() }}.
1.2. Односторонняя привязка к свойствам (Property Binding)
Синтаксис: [property]="expression"
Позволяет привязывать значение свойства DOM-элемента к значению из компонента.
Пример:
<input \[value\]="username">
username = 'admin';
Альтернативный синтаксис через bind-:
bind-value="username"
Используется для привязки любых свойств: [disabled], [src], [ngClass], [style].
1.3. Привязка к событиям (Event Binding)
Синтаксис: (event)="handler"
Позволяет реагировать на события DOM и вызывать методы компонента.
Пример:
<button (click)="onClick()">Нажми меня</button>
onClick() {
console.log('Кнопка нажата');
}
Альтернативный синтаксис через on-:
on-click="onClick()"
Можно передавать $event:
<input (input)="onInput($event)">
1.4. Двусторонняя привязка (Two-Way Binding)
Синтаксис: [(ngModel)]="property"
Обеспечивает одновременную синхронизацию между моделью и представлением. Когда пользователь вводит значение, оно автоматически обновляет свойство компонента и наоборот.
Пример:
<input \[(ngModel)\]="username">
<p>Вы ввели: {{ username }}</p>
username = '';
Для работы с ngModel необходимо подключить FormsModule в модуле:
import { FormsModule } from '@angular/forms';
@NgModule({
imports: \[FormsModule\]
})
За кулисами [(ngModel)]="value" — это синтаксический сахар для:
<input \[ngModel\]="value" (ngModelChange)="value = $event">
2. Особенности выражений в шаблоне
-
Разрешены только безопасные выражения: нельзя использовать присваивания, объявления переменных, вызовы глобальных функций (например, window.alert).
-
Angular шаблонный синтаксис ограничен: нельзя вызывать небезопасные методы или обращаться к глобальному состоянию.
-
Шаблонные выражения вызываются при каждом обнаружении изменений (Change Detection).
3. Атрибуты vs Свойства
Важно различать:
-
Атрибут — HTML-атрибут (например, value="123");
-
Свойство — свойство DOM-объекта (input.value = 123).
Пример:
<!-- Установит атрибут, но не значение поля -->
<input attr.value="123">
<!-- Установит значение в DOM -->
<input \[value\]="123">
В Angular привязка через [] работает с DOM-свойствами, а не с атрибутами.
4. Привязка к стилям и классам
4.1. Привязка к классам
<div \[class.active\]="isActive"></div>
<div \[ngClass\]="{ 'active': isActive, 'disabled': isDisabled }"></div>
4.2. Привязка к стилям
<div \[style.color\]="color"></div>
<div \[ngStyle\]="{ 'font-size': fontSize + 'px' }"></div>
5. Безопасная навигация (?.) и пайпы в шаблоне
Для предотвращения ошибок undefined:
<p>{{ user?.profile?.name }}</p>
Использование пайпов:
<p>{{ birthday | date:'longDate' }}</p>
6. Использование шаблонных переменных
Позволяет ссылаться на элементы DOM или компоненты:
<input #myInput type="text">
<button (click)="logValue(myInput.value)">Log</button>
7. Вложенные компоненты и привязка
Передача данных:
<app-user-card \[user\]="currentUser" (selected)="onUserSelect($event)"></app-user-card>
В дочернем компоненте:
@Input() user: User;
@Output() selected = new EventEmitter<User>();
8. Привязка данных в структурных директивах
*ngIf
<p \*ngIf="isVisible">Показать текст</p>
*ngFor
<li \*ngFor="let item of items; let i = index">{{ i }}: {{ item }}</li>
9. Привязка в реактивных формах
Для реактивных форм используется FormControl и formControl директива:
myControl = new FormControl('');
<form \[formGroup\]="form">
<input formControlName="email">
</form>
10. Механизм Change Detection
Angular отслеживает изменения в модели и автоматически обновляет представление. Это делается при каждом событии (например, click, input, таймеры), используя Zone.js. Когда происходит событие:
-
Angular запускает цикл обнаружения изменений;
-
Все шаблоны проверяются на предмет изменений данных;
-
Все привязки пересчитываются;
-
UI синхронизируется с моделью.
Можно оптимизировать поведение через OnPush стратегию обнаружения изменений:
@Component({
changeDetection: ChangeDetectionStrategy.OnPush
})
11. Привязка к SVG и другим элементам
Angular может привязываться к свойствам SVG и нестандартным элементам:
<svg:rect \[attr.width\]="width" \[attr.height\]="height" \[attr.fill\]="color"></svg:rect>
12. Сценарии комбинированной привязки
<input \[value\]="name" (input)="name = $event.target.value">
Это пример ручной реализации двусторонней привязки без ngModel.
13. Ограничения выражений в привязке
В шаблонах запрещено:
-
Операторы присваивания (=);
-
Декларации переменных (let, const);
-
Вызовы new, window, document;
-
Побочные эффекты.
Цель — избежать XSS, повысить производительность и чистоту шаблонов.