Локальное состояние компонента

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

Определение локального состояния

Локальное состояние компонента в Slim.js определяется через свойства класса, декорированные или просто объявленные внутри класса компонента. Каждое свойство, которое будет участвовать в рендеринге или в реактивной логике, автоматически отслеживается системой Slim.js.

Пример простого компонента с локальным состоянием:

import { Slim, html } from 'slim-js';

class CounterComponent extends Slim {
  count = 0;

  increment() {
    this.count++;
  }

  render() {
    return html`
      <div>
        <p>Текущее значение: ${this.count}</p>
        <button oncl ick=${() => this.increment()}>Увеличить</button>
      </div>
    `;
  }
}

customElements.define('counter-component', CounterComponent);

В этом примере свойство count является локальным состоянием. Любое его изменение автоматически инициирует перерисовку шаблона.

Реактивность и обновление интерфейса

Система реактивности в Slim.js основана на отслеживании изменений локальных свойств компонента. При изменении состояния Slim.js автоматически вызывает рендеринг только для тех частей DOM, которые зависят от изменённого значения.

Особенности реактивности:

  • Автоматическое связывание состояния с шаблоном.
  • Возможность отслеживания сложных объектов и массивов через методы изменения (push, splice, map с перезаписью).
  • Минимизация операций с DOM за счет частичного обновления.
class TodoList extends Slim {
  todos = [];

  addTodo(item) {
    this.todos = [...this.todos, item]; // перезаписываем массив для реактивного обновления
  }

  render() {
    return html`
      <ul>
        ${this.todos.map(todo => html`<li>${todo}</li>`)}
      </ul>
      <button oncl ick=${() => this.addTodo('Новая задача')}>Добавить</button>
    `;
  }
}

Перезапись массива через спред-оператор необходима, чтобы Slim.js смог обнаружить изменение и обновить DOM.

Инициализация состояния

Состояние может инициализироваться напрямую при объявлении свойства или через метод onConnected, который выполняется после добавления компонента в DOM. Это полезно для начальной загрузки данных, выполнения асинхронных операций и настройки внутренних зависимостей.

class UserProfile extends Slim {
  user = null;

  async onConnected() {
    this.user = await fetchUserData();
  }

  render() {
    if (!this.user) return html`<p>Загрузка...</p>`;
    return html`<p>Имя пользователя: ${this.user.name}</p>`;
  }
}

Использование onConnected позволяет безопасно обращаться к DOM и загружать данные перед отображением.

Локальные вычисляемые свойства

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

class ShoppingCart extends Slim {
  items = [];

  get total() {
    return this.items.reduce((sum, item) => sum + item.price, 0);
  }

  render() {
    return html`
      <ul>
        ${this.items.map(item => html`<li>${item.name}: ${item.price} ₽</li>`)}
      </ul>
      <p>Итого: ${this.total} ₽</p>
    `;
  }
}

Вычисляемое свойство total автоматически пересчитывается при изменении массива items, что позволяет держать интерфейс синхронизированным без ручного вызова методов обновления.

Взаимодействие с локальным состоянием через события

Компоненты Slim.js часто взаимодействуют с локальным состоянием через пользовательские события или внутренние методы. События позволяют компонентам сообщать о состоянии родителям или соседям, сохраняя при этом локальную реактивность.

class ToggleSwitch extends Slim {
  isOn = false;

  toggle() {
    this.isOn = !this.isOn;
    this.dispatchEvent(new CustomEvent('toggle', { detail: this.isOn }));
  }

  render() {
    return html`
      <button oncl ick=${() => this.toggle()}>
        ${this.isOn ? 'Вкл' : 'Выкл'}
      </button>
    `;
  }
}

Использование dispatchEvent делает компонент независимым и позволяет другим элементам реагировать на изменения состояния без прямого доступа к внутренним свойствам.

Практические рекомендации

  • Всегда объявлять реактивные свойства напрямую в классе для корректного отслеживания изменений.
  • Для массивов и объектов использовать иммутабельные операции (перезапись, спред-оператор) вместо мутаций.
  • Вычисляемые свойства и геттеры обеспечивают чистый и декларативный способ отображения зависимого состояния.
  • Локальное состояние следует держать максимально узким по области действия: только то, что нужно компоненту для рендеринга и логики.

Локальное состояние в Slim.js объединяет простоту объявления свойств с мощной реактивной системой, позволяя создавать динамичные, эффективные и управляемые компоненты без лишнего кода.