В чём разница между property binding, event binding и two-way binding?
В Angular привязка данных (data binding) представляет собой механизм синхронизации данных между компонентом (моделью) и шаблоном (представлением). Основными видами привязки являются property binding, event binding и two-way binding. Они различаются направлением потока данных и способом взаимодействия между моделью и DOM.
1. Property Binding (Привязка к свойствам)
Суть:
Позволяет передавать данные из компонента в DOM-элемент или дочерний компонент.
Синтаксис:
\[elementProperty\]="componentProperty"
или
\[disabled\]="isDisabled"
\[src\]="imageUrl"
\[ngClass\]="classList"
Пример:
export class AppComponent {
isDisabled = true;
imageUrl = 'https://example.com/image.png';
}
<button \[disabled\]="isDisabled">Кнопка</button>
<img \[src\]="imageUrl">
Особенности:
-
Односторонний поток данных: из модели в шаблон.
-
Работает с DOM-свойствами, а не HTML-атрибутами.
-
Можно использовать с любыми свойствами DOM, директив, компонентов.
2. Event Binding (Привязка к событиям)
Суть:
Позволяет передавать данные из шаблона в компонент, реагируя на события DOM.
Синтаксис:
(eventName)="handler($event)"
Пример:
export class AppComponent {
onClick(event: Event) {
console.log('Кнопка нажата', event);
}
}
<button (click)="onClick($event)">Нажми меня</button>
Особенности:
-
Односторонний поток данных: от шаблона к компоненту.
-
Используется для подписки на стандартные события (click, input, change, submit) и кастомные (@Output).
-
$event содержит объект события DOM или данные, переданные из дочернего компонента.
3. Two-Way Binding (Двусторонняя привязка)
Суть:
Объединяет property binding и event binding в один синтаксис — позволяет синхронизировать значения между компонентом и шаблоном в обе стороны.
Синтаксис:
\[(ngModel)\]="componentProperty"
Пример:
export class AppComponent {
username = '';
}
<input \[(ngModel)\]="username">
<p>Привет, {{ username }}</p>
Как это работает внутри:
\[(ngModel)\]="username" — это синтаксический сахар для:
<input \[ngModel\]="username" (ngModelChange)="username = $event">
Особенности:
-
Двунаправленная синхронизация: изменения в компоненте обновляют DOM, и наоборот.
-
Требует подключения FormsModule из @angular/forms:
import { FormsModule } from '@angular/forms';
@NgModule({ imports: \[FormsModule\] })
- Работает с директивами, которые реализуют интерфейс ControlValueAccessor.
4. Сравнение по направлениям данных
Вид привязки | Поток данных | Сценарий применения |
---|---|---|
Property Binding | Компонент → Шаблон | Отображение данных, управление DOM-свойствами |
--- | --- | --- |
Event Binding | Шаблон → Компонент | Обработка событий от пользователя |
--- | --- | --- |
Two-Way Binding | Компонент ↔ Шаблон | Формы, интерактивные поля, двусторонняя синхронизация |
--- | --- | --- |
5. Пример сравнения в одном компоненте
export class AppComponent {
title = 'Angular';
inputValue = '';
updateValue(event: Event) {
const target = event.target as HTMLInputElement;
this.inputValue = target.value;
}
}
<!-- Property Binding -->
<input \[value\]="inputValue">
<!-- Event Binding -->
<input (input)="updateValue($event)">
<!-- Two-Way Binding -->
<input \[(ngModel)\]="inputValue">
6. Использование в компонентах
Property binding и event binding могут использоваться при взаимодействии с дочерними компонентами:
<app-counter \[count\]="initialCount" (change)="onCounterChange($event)"></app-counter>
// В дочернем компоненте
@Input() count: number;
@Output() change = new EventEmitter<number>();
Two-way binding можно настроить вручную через @Input() и @Output():
<app-counter \[(count)\]="myCount"></app-counter>
@Input() count: number;
@Output() countChange = new EventEmitter<number>();
Angular интерпретирует [(count)]="value" как:
\[count\]="value" (countChange)="value = $event"
7. Отличие от обычных HTML-атрибутов
- [attr.name] — привязка к **атрибуту HTML
** - [property] — привязка к **DOM-свойству
** -
attr.value="..." — обычный HTML-атрибут (работает только при инициализации)
-
[value]="..." — property binding (обновляется при каждом изменении данных)
8. Примеры использования всех типов одновременно
<input \[value\]="name" (input)="name = $event.target.value">
или с двухсторонней привязкой:
<input \[(ngModel)\]="name">
В обоих случаях значение name будет синхронизировано с содержимым поля ввода.
9. Влияние на производительность
-
Property binding и event binding вызывают срабатывание механизма обнаружения изменений (Change Detection);
-
Two-way binding может быть менее производительным при неправильном использовании (например, в больших формах), особенно при частых обновлениях;
-
Для оптимизации используют ChangeDetectionStrategy.OnPush, реактивные формы или ручное управление событиями.