Slim.js — это современная библиотека для создания реактивных пользовательских интерфейсов с использованием Web Components. Одной из ключевых возможностей является организация интерфейса через вложенные компоненты, что обеспечивает модульность, переиспользуемость и удобство поддержки кода.
В Slim.js каждый компонент создаётся через класс, наследующийся от
Slim. Вложенные компоненты можно подключать к родительскому
через обычный HTML-тег, соответствующий имени зарегистрированного
компонента.
Пример создания простого дочернего компонента:
import { Slim } from 'slim-js';
class ChildComponent extends Slim {
get template() {
return `<p>Дочерний компонент: {{message}}</p>`;
}
message = "Привет из ChildComponent";
}
customElements.define('child-component', ChildComponent);
Родительский компонент может использовать этот компонент следующим образом:
class ParentComponent extends Slim {
get template() {
return `
<div>
<h2>Родительский компонент</h2>
<child-component></child-component>
</div>
`;
}
}
customElements.define('parent-component', ParentComponent);
Ключевой момент: Slim.js автоматически создаёт экземпляры дочерних компонентов при рендеринге родителя и обеспечивает реактивную привязку данных внутри каждого компонента.
Slim.js поддерживает реактивные свойства, что позволяет легко передавать данные из родителя в дочерний компонент через атрибуты или свойства.
class ChildComponent extends Slim {
get template() {
return `<p>Привет, {{name}}!</p>`;
}
name = "";
}
customElements.define('child-component', ChildComponent);
class ParentComponent extends Slim {
get template() {
return `
<child-component name="{{userName}}"></child-component>
`;
}
userName = "Алексей";
}
customElements.define('parent-component', ParentComponent);
Slim.js обеспечивает двустороннюю реактивность: если значение
userName изменяется в родителе, дочерний компонент
автоматически обновляет отображение.
Вложенные компоненты особенно полезны при работе с коллекциями
данных. Slim.js поддерживает динамическое создание компонентов через
директиву {{#each}}:
class ItemComponent extends Slim {
get template() {
return `<li>{{item}}</li>`;
}
item = "";
}
customElements.define('item-component', ItemComponent);
class ListComponent extends Slim {
get template() {
return `
<ul>
{{#each items}}
<item-component item="{{this}}"></item-component>
{{/each}}
</ul>
`;
}
items = ["Яблоко", "Банан", "Вишня"];
}
customElements.define('list-component', ListComponent);
В данном примере каждый элемент массива items рендерится
через отдельный экземпляр ItemComponent, сохраняя полную
реактивность.
Slim.js позволяет слушать события дочерних компонентов через
стандартные DOM-события. Вложенный компонент может генерировать
пользовательское событие с помощью dispatchEvent:
class ChildComponent extends Slim {
get template() {
return `<button oncl ick="{{handleClick}}">Нажми меня</button>`;
}
handleClick() {
this.dispatchEvent(new CustomEvent('child-click', { detail: 'Данные от ребенка' }));
}
}
customElements.define('child-component', ChildComponent);
class ParentComponent extends Slim {
get template() {
return `
<child-component onchild-click="{{onChildClick}}"></child-component>
`;
}
onChildClick(event) {
console.log(event.detail); // Выведет: "Данные от ребенка"
}
}
customElements.define('parent-component', ParentComponent);
Особенность Slim.js: привязка событий через
on<event> работает напрямую с методами родителя, что
упрощает коммуникацию между уровнями компонентов.
Каждый компонент Slim.js имеет стандартные хуки жизненного цикла:
onBeforeCreated() — вызывается до создания DOM.onAfterCreated() — вызывается после вставки в DOM.onBeforeUpdate() и onAfterUpdate() —
вызываются при изменении реактивных данных.onBeforeRemoved() — перед удалением компонента из
DOM.Вложенные компоненты наследуют эти хуки, что позволяет родителю управлять состоянием дочерних компонентов через реактивные свойства или события.
class ChildComponent extends Slim {
get template() {
return `<p>{{message}}</p>`;
}
message = "Инициализация...";
onAfterCreated() {
setTimeout(() => {
this.message = "Данные обновлены";
}, 1000);
}
}
customElements.define('child-component', ChildComponent);
Slim.js поддерживает рекурсивные компоненты, что особенно удобно для древовидных структур, таких как меню или комментарии. Для рекурсии важно использовать условие выхода, чтобы избежать бесконечного рендеринга:
class TreeNode extends Slim {
get template() {
return `
<div>
<span>{{name}}</span>
{{#if children}}
<ul>
{{#each children}}
<tree-node name="{{this.name}}" children="{{this.children}}"></tree-node>
{{/each}}
</ul>
{{/if}}
</div>
`;
}
name = "";
children = [];
}
customElements.define('tree-node', TreeNode);
Такой подход позволяет строить глубоко вложенные интерфейсы с полной реактивностью каждого узла.
{{#each}} вместо ручного создания
множества компонентов через JavaScript.В результате Slim.js позволяет строить сложные интерфейсы с минимальной связностью компонентов, обеспечивая модульность и простоту сопровождения кода.