Slim.js — легковесная библиотека для создания веб-компонентов с реактивными свойствами и декларативной разметкой. Одной из ключевых возможностей при работе с компонентами является использование слотов, которые позволяют гибко вставлять контент внутрь компонентов и управлять его отображением.
Слот — это специальный элемент
<slot> внутри шаблона компонента, который служит
местом для вставки внешнего контента. Контент, переданный в слот,
называется assigned nodes. Slim.js поддерживает как
обычные, так и именованные слоты.
Простейший пример:
class MyComponent extends Slim {
get template() {
return `
<div>
<h2>Заголовок компонента</h2>
<slot></slot>
</div>
`;
}
}
customElements.define('my-component', MyComponent);
HTML:
<my-component>
<p>Вставленный контент</p>
</my-component>
В результате <p>Вставленный контент</p>
появится на месте <slot>.
Для управления несколькими зонами вставки используется имя
слота через атрибут name:
class CardComponent extends Slim {
get template() {
return `
<div class="card">
<header><slot name="header"></slot></header>
<main><slot></slot></main>
<footer><slot name="footer"></slot></footer>
</div>
`;
}
}
customElements.define('card-component', CardComponent);
HTML:
<card-component>
<h1 slot="header">Заголовок карточки</h1>
<p>Основной контент</p>
<button slot="footer">Закрыть</button>
</card-component>
В этом случае <slot> без имени используется для
основного контента, а именованные слоты — для отдельных частей
шаблона.
Для работы с контентом слота в коде компонента применяется свойство
this.shadowRoot и методы querySelector или
querySelectorAll для слота, а также
assignedNodes() или assignedElements() для
получения переданного содержимого.
Пример:
class SlotInspector extends Slim {
get template() {
return `
<div>
<slot></slot>
<button id="inspect">Показать содержимое слота</button>
</div>
`;
}
onBeforeCreated() {
this.handleClick = () => {
const slot = this.shadowRoot.querySelector('slot');
const nodes = slot.assignedNodes({ flatten: true });
console.log(nodes);
};
}
onCreated() {
this.shadowRoot.getElementById('inspect')
.addEventListener('click', this.handleClick);
}
}
customElements.define('slot-inspector', SlotInspector);
Метод assignedNodes({ flatten: true }) возвращает массив
всех узлов, переданных в слот, включая текстовые и элементные узлы. Если
требуется получить только элементы, используется
assignedElements().
Slim.js поддерживает реактивность через слоты, но изменения контента,
переданного извне, не вызывают автоматическое обновление состояния
компонента. Для отслеживания динамических изменений применяются события
slotchange.
class DynamicSlot extends Slim {
get template() {
return `<slot></slot>`;
}
onCreated() {
const slot = this.shadowRoot.querySelector('slot');
slot.addEventListener('slotchange', () => {
console.log('Содержимое слота изменилось:', slot.assignedNodes());
});
}
}
customElements.define('dynamic-slot', DynamicSlot);
Событие slotchange срабатывает при добавлении, удалении
или изменении узлов в слоте, что позволяет реализовать реактивное
поведение без дополнительных библиотек.
Для сложных компонентов часто требуется фильтровать или модифицировать узлы слота перед использованием:
const slot = this.shadowRoot.querySelector('slot');
const elements = slot.assignedElements().filter(el => el.tagName === 'LI');
elements.forEach(el => el.style.color = 'blue');
Таким образом можно применять стили, изменять свойства или связывать события только с определёнными элементами.
Slim.js позволяет комбинировать слоты с реактивными свойствами и циклическими конструкциями:
class ListWrapper extends Slim {
items = ['Элемент 1', 'Элемент 2', 'Элемент 3'];
get template() {
return `
<ul>
<slot></slot>
${this.items.map(item => `<li>${item}</li>`).join('')}
</ul>
`;
}
}
customElements.define('list-wrapper', ListWrapper);
Слоты при этом сохраняют вставленный извне контент, а динамически создаваемые элементы отображаются дополнительно. Такой подход позволяет строить гибкие и расширяемые компоненты с комбинированным содержимым.
slot.assignedNodes({ flatten: true }) — возвращает все
узлы, назначенные слоту, включая текстовые.slot.assignedElements() — возвращает только элементные
узлы.slot.addEventListener('slotchange', callback) —
отслеживает изменения содержимого слота.name у <slot> и
slot у дочернего элемента — управление именованными
слотами.Эти инструменты дают полный контроль над содержимым слотов, обеспечивая гибкость при построении сложных веб-компонентов в Slim.js.