Guards и middleware

Slim.js — это лёгкая, реактивная библиотека для создания компонентов на основе Web Components, предоставляющая возможности управления жизненным циклом компонентов, реактивными состояниями и событийной моделью. Одним из ключевых элементов архитектуры Slim.js являются guards и middleware, которые позволяют управлять поведением компонентов, контролировать обновления и внедрять дополнительную логику.


Guards

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

Основные типы guards
  1. Update Guards Применяются перед обновлением DOM, когда изменяется реактивное состояние. Их задача — определить, следует ли выполнять обновление.

    import { Slim, html } from 'slim-js';
    
    class MyComponent extends Slim {
        static get is() { return 'my-component'; }
    
        constructor() {
            super();
            this.count = 0;
        }
    
        increment() {
            this.count++;
        }
    
        guardUpdate(prop, oldValue, newValue) {
            // Обновление произойдет только если новое значение больше старого
            return newValue > oldValue;
        }
    
        render() {
            return html`<button @click=${() => this.increment()}>${this.count}</button>`;
        }
    }
    
    Slim.define(MyComponent);

    В примере метод guardUpdate проверяет значение count и разрешает обновление DOM только при увеличении значения. Это предотвращает ненужные перерисовки.

  2. Action Guards Контролируют выполнение методов компонента. Можно запретить вызов метода в определённых условиях:

    guardAction(methodName, args) {
        if (methodName === 'deleteItem' && !this.userIsAdmin) {
            console.warn('Доступ запрещен');
            return false;
        }
        return true;
    }

    Метод guardAction возвращает false, чтобы заблокировать выполнение действия.

Реактивные guards

Guards можно использовать совместно с реактивными свойствами:

this.propGuard = (prop, oldValue, newValue) => {
    if (prop === 'status' && newValue === 'error') {
        console.error('Нельзя установить статус в error напрямую');
        return false;
    }
    return true;
};

Такой подход позволяет централизованно контролировать все изменения состояния компонента.


Middleware

Middleware в Slim.js — это функции, которые внедряются в жизненный цикл компонентов для выполнения дополнительной логики. Они работают аналогично middleware в Express.js или Vue.js, но применяются к компонентам Web Components.

Жизненные циклы и middleware

Slim.js предоставляет несколько точек для подключения middleware:

  1. Before Render — выполняется перед рендерингом компонента.
  2. After Render — выполняется после рендеринга.
  3. Before Update — выполняется перед обновлением DOM.
  4. After Update — выполняется после обновления DOM.

Пример подключения middleware:

class LoggerMiddleware {
    beforeRender(component) {
        console.log(`Component ${component.tagName} будет отрендерен`);
    }

    afterRender(component) {
        console.log(`Component ${component.tagName} отрендерен`);
    }
}

Slim.use(new LoggerMiddleware());

Middleware можно использовать для:

  • Логирования изменений состояния или действий пользователя.
  • Оборачивания методов компонентов для проверки прав доступа.
  • Добавления глобальной анимации или стилей перед рендером.
  • Управления асинхронными эффектами, такими как запросы к серверу.
Цепочки middleware

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

class AuthMiddleware {
    beforeUpdate(component) {
        if (!component.isAuthenticated) {
            console.warn('Обновление запрещено: пользователь не авторизован');
            return false; // блокируем update
        }
        return true;
    }
}

Slim.use(new LoggerMiddleware());
Slim.use(new AuthMiddleware());

В этом примере AuthMiddleware проверяет авторизацию перед обновлением компонента, а LoggerMiddleware логирует жизненный цикл. Порядок подключения middleware определяет последовательность их выполнения.


Взаимодействие Guards и Middleware

Guards и middleware работают совместно: guards проверяют отдельные свойства и методы компонента, а middleware обеспечивает глобальное или кросс-компонентное управление. При правильной комбинации они позволяют:

  • Минимизировать ненужные обновления DOM.
  • Централизовать контроль за логикой компонентов.
  • Создавать безопасные и предсказуемые реакции на изменения состояния.

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

class SecureComponent extends Slim {
    static get is() { return 'secure-component'; }

    constructor() {
        super();
        this.data = [];
        this.userIsAdmin = false;
    }

    guardUpdate(prop, oldValue, newValue) {
        if (prop === 'data' && !this.userIsAdmin) {
            console.warn('Не разрешено обновлять данные');
            return false;
        }
        return true;
    }

    render() {
        return html`<div>Данные: ${this.data.length}</div>`;
    }
}

class AuditMiddleware {
    afterUpdate(component) {
        console.log(`Компонент ${component.tagName} обновился`);
    }
}

Slim.use(new AuditMiddleware());
Slim.define(SecureComponent);

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


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