Slim.js — это легковесная библиотека для создания веб-компонентов с реактивными возможностями. Одним из ключевых элементов её реактивной архитектуры является подписка на изменения свойств компонентов. Это позволяет автоматически отслеживать изменения состояния и обновлять DOM без ручного вмешательства.
В Slim.js свойства компонента, помеченные как реактивные,
автоматически отслеживаются системой. Для этого используется декоратор
@state или ключевое свойство observed в
компоненте. Любое изменение этих свойств триггерит уведомление для
подписчиков.
Пример декларации реактивного свойства:
import { Slim, html, state } from 'slim-js';
class Counter extends Slim {
@state count = 0;
increment() {
this.count += 1;
}
render() {
return html`
<button @click=${() => this.increment()}>Увеличить</button>
<p>Счётчик: ${this.count}</p>
`;
}
}
customElements.define('my-counter', Counter);
В этом примере count — реактивное свойство. Любое его
изменение автоматически вызовет перерендер компонента.
Slim.js позволяет подписываться на изменения конкретных
свойств через метод onChange. Это полезно, когда
требуется выполнить дополнительные действия при обновлении состояния,
например, синхронизировать данные с сервером или изменять другие
свойства компонента.
Синтаксис использования:
this.onChange('propertyName', (oldValue, newValue) => {
console.log(`Свойство изменилось с ${oldValue} на ${newValue}`);
});
Метод принимает два аргумента:
propertyName — имя свойства для отслеживания;Пример использования в компоненте:
class UserProfile extends Slim {
@state username = '';
constructor() {
super();
this.onChange('username', (oldVal, newVal) => {
console.log(`Имя пользователя изменилось: ${oldVal} → ${newVal}`);
this.validateUsername(newVal);
});
}
validateUsername(value) {
this.isValid = value.length >= 3;
}
render() {
return html`
<input type="text" .value=${this.username} @input=${e => this.username = e.target.value} />
<p>Статус: ${this.isValid ? 'валидный' : 'слишком короткий'}</p>
`;
}
}
customElements.define('user-profile', UserProfile);
В этом примере каждое изменение свойства username
автоматически вызывает проверку валидности имени.
Slim.js поддерживает подписку на несколько свойств
одновременно. Это достигается передачей массива имен свойств в
onChange.
this.onChange(['propA', 'propB'], (oldValue, newValue, propertyName) => {
console.log(`${propertyName} изменилось: ${oldValue} → ${newValue}`);
});
Такой подход упрощает обработку взаимосвязанных данных и позволяет минимизировать дублирование кода.
Для освобождения ресурсов и предотвращения утечек памяти Slim.js
предоставляет возможность отписки. Метод
offChange используется для удаления подписчика:
const callback = (oldVal, newVal) => { console.log(newVal); };
this.onChange('count', callback);
// Позже
this.offChange('count', callback);
Если отписка не выполнена, подписчики продолжают получать уведомления, что может привести к неожиданным побочным эффектам.
Иногда нужно реагировать на любое изменение любого
реактивного свойства. Для этого используется метод
observeAll:
this.observeAll((propertyName, oldVal, newVal) => {
console.log(`Свойство ${propertyName} изменилось: ${oldVal} → ${newVal}`);
});
Этот метод полезен при отладке или при создании компонентов с динамическими связями между свойствами.
@computed) вместе с
onChange для оптимизации обновлений.class ShoppingCart extends Slim {
@state items = [];
@state total = 0;
constructor() {
super();
this.onChange('items', () => this.calculateTotal());
}
addItem(item) {
this.items = [...this.items, item]; // важно создавать новый массив для реактивности
}
calculateTotal() {
this.total = this.items.reduce((sum, item) => sum + item.price, 0);
}
render() {
return html`
<ul>
${this.items.map(item => html`<li>${item.name}: $${item.price}</li>`)}
</ul>
<p>Итого: $${this.total}</p>
<button @click=${() => this.addItem({ name: 'Apple', price: 1 })}>Добавить яблоко</button>
`;
}
}
customElements.define('shopping-cart', ShoppingCart);
В этом компоненте изменения массива items автоматически
запускают перерасчет total, обеспечивая согласованность
данных без ручного вызова обновления DOM.
Подписка на изменения в Slim.js является ядром реактивного программирования в библиотеке, обеспечивая автоматическое обновление интерфейса, синхронизацию данных и гибкую архитектуру компонентов. Она позволяет строить сложные динамические приложения с минимальными усилиями по управлению состоянием и DOM.