Two-way data binding

Two-way data binding — это механизм, который обеспечивает синхронизацию данных между моделью и представлением. В Ember.js этот механизм реализован через свойства и методы, которые позволяют эффективно обновлять пользовательский интерфейс при изменении данных и наоборот.

Основные принципы

В Ember.js концепция двухсторонней привязки данных заключается в том, что изменения, происходящие в модели, автоматически отражаются на представлении, и наоборот — изменения, сделанные пользователем в интерфейсе, моментально передаются обратно в модель. Это достигается через computed properties и bindings. Ember.js не использует стандартное двухстороннее связывание, как это реализовано в некоторых других фреймворках, таких как Angular, но позволяет получать схожий функционал через комбинацию своих мощных средств работы с данными.

Механизм двухсторонней привязки данных

Ember.js использует концепцию observers и computed properties для реализации двусторонней привязки. С помощью этих инструментов фреймворк отслеживает изменения в данных и обновляет представление, а также позволяет получать изменения в интерфейсе и сразу применять их к данным.

Пример базовой привязки
// Контроллер с моделью
import Controller from '@ember/controller';

export default Controller.extend({
  firstName: 'John',
  lastName: 'Doe',
});
<!-- Шаблон с привязкой данных -->
<input type="text" value={{firstName}} />
<input type="text" value={{lastName}} />

В этом примере модель имеет два свойства — firstName и lastName. Свойства привязаны к полям ввода через шаблон, используя синтаксис {{firstName}} и {{lastName}}. Это значит, что любые изменения в полях ввода будут автоматически обновлять свойства модели. Если свойства модели изменятся, то соответствующие значения в полях ввода также будут обновляться.

Двусторонняя привязка через события

Ember.js позволяет реагировать на изменения в интерфейсе и передавать их в модель с помощью обработчиков событий. Для этого используется input или change события. Важно понимать, что с помощью этих событий данные модели можно синхронизировать с полями ввода.

// Контроллер с обработчиками событий
import Controller from '@ember/controller';

export default Controller.extend({
  firstName: 'John',
  lastName: 'Doe',
  
  actions: {
    updateFirstName(newFirstName) {
      this.set('firstName', newFirstName);
    },
    updateLastName(newLastName) {
      this.set('lastName', newLastName);
    }
  }
});
<!-- Шаблон с обработчиками событий -->
<input type="text" value={{firstName}} {{on "input" (fn this.updateFirstName)}} />
<input type="text" value={{lastName}} {{on "input" (fn this.updateLastName)}} />

Здесь на событие input добавлен обработчик, который обновляет соответствующие свойства модели. Важно отметить, что для создания двухсторонней привязки с полями ввода используются действия {{on}} и синтаксис {{fn this.updateFirstName}}.

Синхронизация с моделью данных

Ember.js поддерживает two-way binding с использованием tracked properties, которые синхронизируются с отображением модели данных. Для этого используется декоратор @tracked, который позволяет отслеживать изменения в свойствах и автоматически обновлять представление.

// Контроллер с использованием tracked properties
import Controller from '@ember/controller';
import { tracked } from '@glimmer/tracking';

export default class extends Controller {
  @tracked firstName = 'John';
  @tracked lastName = 'Doe';
}
<!-- Шаблон с использованием tracked properties -->
<input type="text" value={{this.firstName}} {{on "input" (fn this.updateFirstName)}} />
<input type="text" value={{this.lastName}} {{on "input" (fn this.updateLastName)}} />

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

Роль computed properties в привязке данных

Computed properties в Ember.js играют важную роль в механизме двухсторонней привязки. С помощью вычисляемых свойств можно не только изменять данные модели, но и выполнять дополнительные вычисления, основанные на этих данных. Это дает возможность создавать более сложные взаимодействия в приложении.

// Контроллер с вычисляемым свойством
import Controller from '@ember/controller';
import { computed } from '@ember/object';

export default Controller.extend({
  firstName: 'John',
  lastName: 'Doe',

  fullName: computed('firstName', 'lastName', function() {
    return `${this.firstName} ${this.lastName}`;
  }),

  actions: {
    updateFullName(newFullName) {
      const [firstName, lastName] = newFullName.split(' ');
      this.set('firstName', firstName);
      this.set('lastName', lastName);
    }
  }
});
<!-- Шаблон с использованием вычисляемого свойства -->
<input type="text" value={{fullName}} {{on "input" (fn this.updateFullName)}} />

В этом примере свойство fullName является вычисляемым, и при изменении значений firstName и lastName оно автоматически пересчитывается. Изменения в поле ввода вызывают действие, которое обновляет обе части имени, тем самым синхронизируя данные.

Особенности двухсторонней привязки в Ember.js

Ember.js не имеет “глобальной” двусторонней привязки, как, например, Angular. Вместо этого каждый компонент и контроллер в Ember.js имеет явное управление данными и их представлением. Это дает большую гибкость и контроль над поведением приложения.

  • Явная синхронизация: В Ember.js необходимо явно связывать данные с представлением через шаблоны и обработчики событий, что позволяет избежать неожиданного поведения и сложных случаев для отладки.

  • Работа с компонентами: Для реализации двухсторонней привязки в компонентах используется механизм actions и @tracked. Компоненты могут управлять своим состоянием и синхронизировать его с родительскими моделями.

  • Использование шаблонных выражений: В Ember.js синтаксис {{}} в шаблонах используется для привязки данных, а обработчики событий, такие как {{on}}, позволяют эффективно управлять изменениями данных в модели.

Резюме

В Ember.js двусторонняя привязка данных основывается на принципах observables и computed properties. Эти средства позволяют создать гибкую и эффективную архитектуру, при которой изменения модели автоматически отображаются в представлении, а изменения в интерфейсе обновляют модель. Важно понимать, что механизм двухсторонней привязки в Ember.js работает через явное связывание данных, что дает разработчику полный контроль над поведением приложения и упрощает отладку.