Управление внутренним состоянием

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

Slim-компонент определяет состояние на уровне экземпляра класса. Для этого используются обычные поля или геттеры/сеттеры, а также вспомогательные методы для реактивного обновления представления.

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

Базовая инициализация выполняется в конструкторе или при объявлении полей класса:

class Counter extends Slim {
  count = 0;
}

Переменные, определённые таким образом, автоматически становятся частью реактивного состояния. В шаблоне к ним обращаются через двойные фигурные скобки:

<span>{{count}}</span>

Изменение состояния

Ключевой момент: состояние должно изменяться через присвоение. Slim.js отслеживает сеттер и инициирует обновление представления:

increment() {
  this.count++;
}

При вызове метода increment шаблон обновляется без дополнительных вызовов рендеринга.

Вычислимые свойства

Сложные зависимости внутри компонента удобно инкапсулировать в вычислимые геттеры:

get doubled() {
  return this.count * 2;
}

В шаблоне вычислимое свойство ведёт себя как обычное состояние:

<span>{{doubled}}</span>

Вычисление выполняется при каждом обновлении зависимости, не требуя ручного кэширования.

Привязка методов к состоянию

Slim.js позволяет связывать события интерфейса с методами компонента:

<button click="increment">+</button>

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

Наблюдение за изменениями

Сложные компоненты нередко используют специальные методы для отслеживания изменений. Slim.js предоставляет хук onBeforeUpdate и onAfterUpdate. Они позволяют выполнять дополнительные действия при изменениях состояния:

onAfterUpdate(prop, value) {
  if (prop === 'count' && value > 10) {
    console.log('Порог достигнут');
  }
}

Система передаёт имя изменившегося поля и новое значение, что упрощает построение внутренних реакций и валидации.

Внутреннее состояние и свойства компонента

Slim.js различает два уровня данных: внутреннее состояние и публичные свойства. Публичные свойства доступны через атрибуты:

<counter initial="5"></counter>

Компонент принимает значение атрибута и может использовать его для инициализации состояния:

onCreated() {
  this.count = Number(this.initial);
}

Публичные свойства работают как интерфейс обмена данными между компонентами, а состояние остаётся локальным.

Состояние и жизненный цикл

Slim-компонент проходит ряд стадий: создание, монтирование, обновление, удаление. Внутреннее состояние присутствует на всех этапах. Инициализация может происходить в onCreated, а интеграция с DOM — в onAdded:

onAdded() {
  this.count = 1;
}

Изменение состояния в ранних хуках приводит к первичному рендерингу без лишних перерисовок.

Асинхронное обновление

В Slim.js обновления состояния пакетируются. При множественных изменениях переменных в рамках одного синхронного блока обновление шаблона выполняется один раз. Это снижает нагрузку на DOM и повышает производительность:

batchUpdate() {
  this.count++;
  this.count++;
  this.count++;
}

Вёрстка обновится единоразово после завершения метода.

Состояние и шаблонные конструкции

Slim.js поддерживает условные и повторяющиеся конструкции с использованием состояния. Например:

<div s:if="count > 0">
  Положительное значение
</div>

Для списков:

<li s:repeat="item in items">
  {{item}}
</li>

Эти директивы синхронизируются с изменениями состояния и корректно обновляют DOM по мере их появления, удаления или изменения.

Инкапсуляция и приватность

Внутреннее состояние не должно зависеть от внешнего окружения. Такая изоляция облегчает тестирование и повторное использование компонентов. Slim.js поощряет приватные поля:

#internalValue = 0;

Приватность предотвращает непредсказуемые изменения извне и обеспечивает стабильность работы.

Состояние и взаимодействие компонентов

Передача данных между компонентами осуществляется через свойства и события. Внутреннее состояние никогда не передаётся напрямую. Потомок может генерировать событие, а родитель обновлять своё состояние в ответ:

this.dispatchEvent(new CustomEvent('update', { detail: value }));

Такой паттерн обеспечивает однонаправленный поток данных и снижает связанность.

Работа с необязательными и сложными структурами

Состояние может включать сложные структуры: объекты, массивы, карты. Slim.js отслеживает только ссылку. Изменения внутри структуры требуют обновления ссылки, иначе шаблон не узнает об изменении:

this.items = [...this.items, newItem];

Пересоздание структуры сохраняет реактивность даже при глубоко вложенных данных.

Контроль обновлений и оптимизация

При большом объёме состояния возникает необходимость выбора минимального набора данных для обновления шаблона. Slim.js позволяет оптимизировать шаблон с помощью отдельных подкомпонентов и избирательных вычислений. Разделение крупного состояния на логические участки предотвращает избыточную перерисовку.

Состояние и серверные данные

Асинхронный запрос к серверу обычно инициируется после монтирования компонента:

async onAdded() {
  const response = await fetch('/api/data');
  this.items = await response.json();
}

Полученные данные становятся частью состояния и автоматически приводят к перерисовке компонента.

Обработка ошибок и состояние

Ошибки при изменении состояния отслеживаются отдельно от отображения. Slim.js предоставляет механизмы обработки ошибок уровня компонента, что позволяет хранить ошибки в специальном поле:

try {
  this.count = parseInt(value);
} catch(e) {
  this.error = e.message;
}

Шаблон может отображать текущее состояние ошибки без вмешательства в логику вычислений.

Итеративное развитие состояния

Эволюция состояния внутри компонента происходит по мере усложнения сценариев использования. На ранних этапах используются простые примитивы, затем вводятся вычислимые геттеры, события, хранилища и серверные данные. Slim.js сохраняет единый принцип: любое изменение состояния ведёт к обновлению представления и синхронизации логики с UI.