Реактивность свойств

SkateJS — это библиотека для создания веб-компонентов на JavaScript, которая строится вокруг реактивной модели данных и декларативного обновления интерфейса. Одной из ключевых особенностей является реактивность свойств — механизм, позволяющий автоматически обновлять DOM при изменении состояния компонента.


Определение свойств

В SkateJS свойства компонента описываются через объект props. Каждое свойство может иметь тип, значение по умолчанию и флаги реактивности.

import { define, props, Component } from 'skatejs';

class MyComponent extends Component {
  static props = {
    name: props.string,
    age: props.number,
    active: { ...props.boolean, default: false }
  };

  renderCallback() {
    this.textContent = `${this.name} — ${this.age} лет`;
  }
}

define('my-component', MyComponent);

Ключевые моменты:

  • props.string, props.number, props.boolean — предопределённые типы с автоматической проверкой.
  • Свойства могут иметь значения по умолчанию через поле default.
  • Изменение свойства инициирует вызов renderCallback, что обеспечивает реактивное обновление интерфейса.

Изменение свойств и реактивность

SkateJS отслеживает изменения свойств через механизм наблюдения (getter/setter). При изменении значения свойства автоматически вызывается метод рендера, который может обновить DOM.

const component = document.createElement('my-component');
component.name = 'Алексей';
component.age = 30;

// После установки свойств автоматически обновится текст внутри компонента
document.body.appendChild(component);

Особенности:

  • Любое изменение свойства через присваивание (component.name = 'Никита') мгновенно отражается в компоненте.
  • Можно комбинировать свойства с разными типами, SkateJS гарантирует корректную типизацию и реактивность.

Свойства с кастомной реактивностью

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

class MyComponent extends Component {
  static props = {
    count: {
      ...props.number,
      set(el, { oldValue, newValue }) {
        console.log(`Старое значение: ${oldValue}, новое: ${newValue}`);
        return newValue;
      }
    }
  };

  renderCallback() {
    this.textContent = `Счётчик: ${this.count}`;
  }
}
  • Функция set вызывается при каждом изменении свойства.
  • Возвращаемое значение используется как новое значение свойства.
  • Можно реализовать валидацию, трансформацию или дополнительную логику перед обновлением интерфейса.

Реактивность массивов и объектов

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

class MyComponent extends Component {
  static props = {
    items: props.array
  };

  renderCallback() {
    this.innerHTML = this.items.map(item => `<div>${item}</div>`).join('');
  }
}

const component = document.createElement('my-component');
component.items = ['apple', 'banana'];
component.items.push('orange');
component.items = [...component.items]; // Явное уведомление о изменении
  • Изменение массива через методы вроде push не вызывает renderCallback.
  • Необходима иммутабельная замена массива, чтобы реактивность сработала.

Наблюдение за свойствами

SkateJS позволяет подписываться на изменения свойств с помощью колбэка updated.

class MyComponent extends Component {
  static props = {
    active: props.boolean
  };

  updated(oldProps, newProps) {
    if (oldProps.active !== newProps.active) {
      console.log(`Active изменилось с ${oldProps.active} на ${newProps.active}`);
    }
  }
}
  • Метод updated получает старые и новые значения всех свойств.
  • Можно реализовать дополнительные эффекты без прямого вмешательства в renderCallback.

Взаимодействие с атрибутами

Свойства SkateJS автоматически синхронизируются с атрибутами HTML, если это указано:

class MyComponent extends Component {
  static props = {
    name: { ...props.string, attribute: true }
  };
}

const element = document.createElement('my-component');
element.setAttribute('name', 'Ирина');
// В свойстве `element.name` автоматически появится значение 'Ирина'
  • Свойства, привязанные к атрибутам, позволяют использовать компонент полностью декларативно в HTML.
  • Обратная синхронизация также работает: изменение свойства обновляет атрибут.

Вывод

Реактивность свойств в SkateJS обеспечивает прозрачное связывание данных с интерфейсом. Основные возможности включают:

  • Определение свойств с типами и значениями по умолчанию.
  • Автоматическое обновление DOM при изменении свойства.
  • Кастомные обработчики set для управления логикой изменения.
  • Поддержка сложных типов через иммутабельные операции.
  • Подписка на изменения через updated.
  • Связывание с HTML-атрибутами для декларативного использования.

Реактивная модель SkateJS позволяет создавать сложные веб-компоненты без явного управления состоянием и обновлением интерфейса, сохраняя при этом контроль над типизацией и валидацией данных.