Слоты в Stencil — это механизмы, которые позволяют внедрять контент в компоненты. Подобно слоту в шаблонизаторах или других фреймворках, Stencil использует их для динамической вставки пользовательского контента в заранее определённые места компонента. Это мощный инструмент для создания повторно используемых и гибких компонентов, позволяющий разработчику контролировать, где и как будет отображаться пользовательский контент, не изменяя структуру компонента.
Слот в Stencil — это область в компоненте, которая может быть заполнена внешним содержимым. Вся суть концепции слотов заключается в том, что компонент заранее определяет места, в которые пользователь может вставить свои данные. При этом сам компонент остаётся независимым и универсальным, а контент, переданный в слот, может быть обработан в зависимости от контекста использования.
Слоты в Stencil реализуются с помощью элемента
<slot>, который вставляется в разметку компонента.
Этот элемент указывает место, где будет рендериться контент, переданный
компоненту при его использовании.
Самый простой пример использования слота выглядит следующим образом:
@Component({
tag: 'my-component',
styleUrl: 'my-component.css',
shadow: true
})
export class MyComponent {
render() {
return (
<div>
<h1>Заголовок компонента</h1>
<slot></slot>
</div>
);
}
}
В этом примере компонент my-component содержит слот.
Когда компонент будет использован в другом месте приложения, в слот
можно передать дополнительный контент:
<my-component>
<p>Это пользовательский контент, который будет вставлен в слот.</p>
</my-component>
При рендере компонента контент, переданный в слот, будет отображён
там, где находится <slot></slot> в шаблоне
компонента.
Слоты могут принимать аттрибуты, что даёт возможность точнее настроить, какой контент куда будет вставляться. Например, можно задать несколько слотов с разными именами:
@Component({
tag: 'my-component',
styleUrl: 'my-component.css',
shadow: true
})
export class MyComponent {
render() {
return (
<div>
<h1>Заголовок компонента</h1>
<slot name="header"></slot>
<slot></slot>
<slot name="footer"></slot>
</div>
);
}
}
Теперь при использовании компонента можно указать, в какой слот передаётся контент:
<my-component>
<div slot="header">Заголовок, вставленный в слот</div>
<p>Это основной контент компонента.</p>
<div slot="footer">Футер, вставленный в слот</div>
</my-component>
В данном случае контент, переданный в слот с аттрибутом
name="header", будет отображён в месте, где находится
<slot name="header"></slot>, а контент в слот
по умолчанию будет вставлен в первый слот.
Если слот не имеет переданного контента, можно указать дефолтное содержимое, которое будет использоваться, если в слот ничего не было передано. Это полезно для задания fallback-контента.
@Component({
tag: 'my-component',
styleUrl: 'my-component.css',
shadow: true
})
export class MyComponent {
render() {
return (
<div>
<h1>Заголовок компонента</h1>
<slot>
<p>Дефолтный контент, если ничего не передано в слот.</p>
</slot>
</div>
);
}
}
Если компонент будет использован без передачи контента в слот, то вместо пустого места появится указанный дефолтный контент. В случае передачи контента, он заменит дефолтный.
Stencil предоставляет возможность работать с слотами через API, что позволяет получать доступ к содержимому слота и манипулировать им на уровне JavaScript.
Например, можно использовать метод slot.assignedNodes(),
чтобы получить все элементы, переданные в слот:
@Component({
tag: 'my-component',
styleUrl: 'my-component.css',
shadow: true
})
export class MyComponent {
@Element() el: HTMLElement;
componentDidLoad() {
const slot = this.el.shadowRoot.querySelector('slot');
const assignedNodes = slot.assignedNodes();
console.log(assignedNodes);
}
render() {
return (
<div>
<h1>Заголовок компонента</h1>
<slot></slot>
</div>
);
}
}
Этот код позволит вывести все узлы, переданные в слот, после того как компонент будет загружен.
Stencil использует реактивность для обработки состояний компонента. Слоты тоже могут быть связаны с реактивными данными, например, для того чтобы динамически изменять содержимое, передаваемое в слот.
@Component({
tag: 'my-component',
styleUrl: 'my-component.css',
shadow: true
})
export class MyComponent {
@State() content: string = 'Пользовательский контент';
render() {
return (
<div>
<h1>Заголовок компонента</h1>
<slot>{this.content}</slot>
</div>
);
}
}
Здесь содержимое слота зависит от состояния компонента, и при изменении этого состояния содержимое, переданное в слот, будет автоматически обновляться.
Слоты являются важной частью концепции компонентов в Stencil, позволяя эффективно разделять структуру и контент, а также создавать гибкие и переиспользуемые компоненты. Механизм слотов позволяет управлять местом вставки контента, что делает компоненты более универсальными и легко настраиваемыми.