Одной из ключевых особенностей Slim.js является реактивное обновление DOM без полной перерисовки компонентов. Неправильное управление изменениями состояния может привести к лишним перерисовкам, что снижает производительность, особенно при работе с большими списками или сложными интерфейсами. Slim.js предоставляет механизмы для тонкой настройки реактивности и минимизации операций с DOM.
В Slim.js реактивность строится на свойствах, объявленных через
@state или @property. Любое изменение таких
свойств автоматически инициирует обновление компонента:
import { Slim, html, state } from 'slim-js';
class Counter extends Slim {
@state count = 0;
increment() {
this.count++;
}
render() {
return html`<div>
<p>Счётчик: ${this.count}</p>
<button @click=${() => this.increment()}>Увеличить</button>
</div>`;
}
}
customElements.define('my-counter', Counter);
Особенности работы:
Для уменьшения количества перерисовок рекомендуется делить состояние на мелкие, независимые свойства, вместо хранения всех данных в одном объекте:
@state firstName = '';
@state lastName = '';
@state age = 0;
Если объединить все данные в один объект:
@state user = { firstName: '', lastName: '', age: 0 };
Любое изменение одного поля (user.firstName = 'Иван')
приведёт к полной перерисовке всего блока, где используется
user. Разделение свойств делает обновления локальными.
Slim.js поддерживает геттеры, которые могут
выступать в роли вычисляемых свойств. Такие свойства не хранят состояние
напрямую, но реагируют на изменения зависимых @state
полей:
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
В шаблоне fullName обновляется автоматически при
изменении firstName или lastName, при этом
Slim.js минимизирует изменение только текстового узла, а не всего
родительского элемента.
При рендеринге списков важно использовать key для
каждого элемента, чтобы Slim.js мог правильно дифференцировать элементы
и избегать полной перерисовки списка:
<ul>
${this.items.map(item => html`<li key=${item.id}>${item.name}</li>`)}
</ul>
Без key Slim.js может пересоздать все элементы списка
при каждом обновлении, даже если изменился только один элемент. С
key изменяется только конкретный элемент, что значительно
снижает нагрузку на DOM.
События, привязанные через синтаксис @event,
автоматически управляются Slim.js. Для минимизации лишних
перерисовок:
@state инициирует реактивное обновление.Пример:
<button @click=${() => this.toggleActive()}>Переключить</button>
Изменение локального состояния внутри метода
toggleActive() обновит только необходимые узлы.
requestUpdate()Иногда требуется принудительное обновление части
шаблона без изменения всех реактивных свойств. Для этого можно
использовать метод requestUpdate() с указанием конкретного
свойства:
this.requestUpdate('count');
Это полезно, когда состояние обновляется асинхронно или обрабатывается вне стандартного реактивного механизма Slim.js.
Пример мемоизации:
get filteredItems() {
if (!this._cached || this._lastFilter !== this.filter) {
this._cached = this.items.filter(item => item.name.includes(this.filter));
this._lastFilter = this.filter;
}
return this._cached;
}
Slim.js автоматически обновляет только те компоненты, чьи свойства изменились. Для оптимизации:
@property.<child-component .value=${this.someValue}></child-component>
Использование ссылочного типа объекта без изменений приведёт к ненужной перерисовке. Лучше передавать примитив или отдельное поле объекта.
key при работе со списками.requestUpdate() для точечных
обновлений.Эти подходы позволяют Slim.js работать максимально эффективно, снижая нагрузку на DOM и улучшая отзывчивость интерфейсов даже при больших объёмах данных.