Создание собственных директив

Slim.js предоставляет гибкий механизм для расширения функциональности компонентов через директивы. Директива — это способ привязки поведения к элементам DOM, который позволяет реализовать повторно используемые шаблонные паттерны и реактивное управление состоянием. Пользовательские директивы особенно полезны для внедрения специфической логики без изменения базового кода компонента.

Регистрация директив

Для создания собственной директивы используется метод Slim.directive. Он принимает два обязательных аргумента:

  1. Имя директивы — строка, которая будет использоваться в HTML-шаблоне.
  2. Функция обработчика — функция, которая выполняется при применении директивы к элементу.
Slim.directive('highlight', function(element, value) {
    element.style.backgroundColor = value || 'yellow';
});

В примере выше создается директива highlight, которая окрашивает элемент в указанный цвет. Если значение не передано, применяется цвет по умолчанию.

Синтаксис использования в шаблоне

После регистрации директива применяется как атрибут элемента:

<div highlight="lightblue">Текст с подсветкой</div>

Директива автоматически получает элемент и значение атрибута. Значение можно динамически связывать с реактивным свойством компонента:

<div highlight="{{color}}">Динамическая подсветка</div>

Работа с реактивными данными

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

  • Проверять наличие нового значения;
  • Обновлять DOM только при изменении состояния.
Slim.directive('toggleVisibility', function(element, value) {
    element.style.display = value ? 'block' : 'none';
});
<div toggle-visibility="{{isVisible}}">Скрываемый блок</div>

При изменении свойства isVisible элемент автоматически отображается или скрывается.

Доступ к атрибутам и событиям

Внутри функции директивы доступ к элементу DOM предоставляется первым аргументом. Для работы с атрибутами можно использовать:

Slim.directive('dataInfo', function(element) {
    console.log(element.dataset.info);
});

Для подписки на события создается обычный обработчик:

Slim.directive('logClick', function(element) {
    element.addEventListener('click', () => console.log('Элемент кликнут'));
});

Удаление и обновление директив

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

  • connectedCallback — вызывается при вставке элемента в DOM;
  • disconnectedCallback — вызывается при удалении элемента из DOM.

Директива может хранить состояние через свойство element._slimState, чтобы отслеживать предыдущие значения и корректно обновлять поведение.

Slim.directive('countClicks', function(element) {
    if (!element._slimState) element._slimState = { count: 0 };
    element.addEventListener('click', () => {
        element._slimState.count++;
        element.textContent = `Клики: ${element._slimState.count}`;
    });
});

Параметры и выражения

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

Slim.directive('styleWidth', function(element, value) {
    element.style.width = `${value}px`;
});
<div style-width="{{width}}">Ширина динамическая</div>

Здесь свойство width компонента управляет шириной элемента без прямого вмешательства в DOM.

Совмещение нескольких директив

Один элемент может использовать несколько директив одновременно. Каждая директива получает ссылку на элемент и своё значение:

<div highlight="{{bgColor}}" toggle-visibility="{{isVisible}}">Комбинированный блок</div>

Это позволяет создавать модульные и переиспользуемые паттерны поведения.

Передача функций

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

Slim.directive('onHover', function(element, fn) {
    element.addEventListener('mouseenter', fn);
});
<button on-hover="{{() => alert('Навели мышь')}}">Наведи на меня</button>

Рекомендации по проектированию директив

  • Держать директиву максимально самодостаточной, чтобы она не зависела от внешнего состояния за пределами реактивных свойств.
  • Не изменять DOM без необходимости, чтобы не нарушить производительность.
  • Использовать _slimState для хранения промежуточных данных между обновлениями.
  • Давать директивам говорящие имена, отражающие их поведение.

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