Преобразование типов

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

Объявление свойств и их типы

В Slim.js свойства компонента объявляются через объект properties. Для каждого свойства можно задать:

  • Тип (type) — определяет, к какому типу будут приведены значения при присвоении.
  • Значение по умолчанию (default) — используется, если свойство не передано.
  • Наблюдатель (observer) — функция, вызываемая при изменении значения свойства.

Пример объявления свойств с типами:

class MyComponent extends Slim {
  get useShadow() { return true; }

  get properties() {
    return {
      name: { type: String, default: "Без имени" },
      age: { type: Number, default: 0 },
      isActive: { type: Boolean, default: false }
    };
  }

  render() {
    return `<div>
              <p>Имя: ${this.name}</p>
              <p>Возраст: ${this.age}</p>
              <p>Активен: ${this.isActive}</p>
            </div>`;
  }
}

customElements.define('my-component', MyComponent);

В этом примере свойства автоматически конвертируются в указанные типы:

  • Строка (String) — любое присвоенное значение преобразуется в строку.
  • Число (Number) — применяется Number(value), что позволяет корректно обрабатывать числовые строки.
  • Булев тип (Boolean) — любое значение, кроме false, 0, null, undefined и пустой строки, интерпретируется как true.

Механизм преобразования

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

  1. String: вызывается String(value).

    this.name = 123; // преобразуется в "123"
  2. Number: вызывается Number(value).

    this.age = "42"; // преобразуется в 42
    this.age = "abc"; // преобразуется в NaN
  3. Boolean: приводится к логическому значению.

    this.isActive = "true"; // преобразуется в true
    this.isActive = 0;      // преобразуется в false
  4. Array / Object: переданное значение ожидается в виде массива или объекта. Slim.js не выполняет глубокого парсинга строк, поэтому JSON-строки нужно парсить вручную.

    this.items = '[1,2,3]'; // не преобразуется автоматически
    this.items = JSON.parse('[1,2,3]');

Наблюдение и реактивность при изменении типов

Свойства Slim.js поддерживают реактивность. Наблюдатели (observer) вызываются после преобразования значения:

get properties() {
  return {
    count: { type: Number, default: 0, observer: this.countChanged }
  };
}

countChanged(oldValue, newValue) {
  console.log(`Счетчик изменен с ${oldValue} на ${newValue}`);
}

При присвоении component.count = "15"; значение автоматически преобразуется в число 15, а затем вызывается метод countChanged.

Преобразование для атрибутов

Slim.js синхронизирует свойства с HTML-атрибутами. Если задать свойство через атрибут:

<my-component age="30" is-active="true"></my-component>

Slim.js автоматически выполнит преобразование типов:

  • Атрибут age="30" → свойство age = 30 (Number)
  • Атрибут is-active="true" → свойство isActive = true (Boolean)

Особенность булевых атрибутов: наличие атрибута уже трактуется как true, отсутствие — как false. Например:

<my-component is-active></my-component> <!-- isActive = true -->
<my-component></my-component>          <!-- isActive = false -->

Пользовательские преобразователи

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

get properties() {
  return {
    price: {
      type: Number,
      converter: value => parseFloat(value.replace(/\$/g, '')),
      default: 0
    }
  };
}

Теперь атрибут price="$99.99" преобразуется в число 99.99. Это особенно полезно при работе с нестандартными форматами данных.

Типизация сложных объектов

Для массивов и объектов стандартное преобразование не всегда достаточно. Для таких случаев используют:

  • Getter/Setter с внутренним хранением:
get items() { return this._items || []; }
set items(value) {
  this._items = Array.isArray(value) ? value : [];
  this.requestUpdate();
}
  • Парсинг JSON при приеме строковых атрибутов:
set config(value) {
  try {
    this._config = typeof value === "string" ? JSON.parse(value) : value;
  } catch {
    this._config = {};
  }
}

Рекомендации по использованию преобразований

  • Всегда указывать type для свойств, которые могут быть переданы через атрибуты.
  • Для булевых свойств полагаться на наличие/отсутствие атрибута.
  • Для сложных данных использовать converter или парсинг JSON.
  • Проверять значения после преобразования при необходимости точного контроля.

Особенности реактивного обновления

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

this.age = "25"; // преобразуется в число 25
this.age = 25;   // изменений нет, рендеринг не вызывается

Таким образом, правильное использование типов в Slim.js обеспечивает:

  • Корректную интерпретацию данных.
  • Стабильную реактивность и вызов наблюдателей.
  • Простое связывание свойств с атрибутами HTML.