Stencil предоставляет мощный механизм для создания и использования custom elements (кастомных элементов) в веб-приложениях. Это стандарт веб-компонентов, который позволяет разработчикам создавать повторно используемые, инкапсулированные компоненты с минимальной зависимостью от внешних библиотек. В Stencil процесс создания кастомных элементов интуитивно понятен, при этом он предлагает высокую производительность и совместимость с существующими фреймворками и библиотеками.
Кастомные элементы представляют собой пользовательские HTML-элементы,
которые можно использовать в любом HTML-документе так же, как и
стандартные элементы, такие как <div>,
<input>, или <button>. Для
создания кастомного элемента используется API
CustomElementRegistry, которое позволяет зарегистрировать
новый элемент и привязать к нему логику. В Stencil эта логика упрощена и
организована в виде компонентов, которые можно настраивать через
атрибуты и события.
Компонент в Stencil — это класс, который расширяет базовый класс
Component. Он может быть использован для создания
кастомного элемента, который затем может быть зарегистрирован в
глобальном реестре. Рассмотрим базовую структуру компонента:
import { Component, h } from '@stencil/core';
@Component({
tag: 'my-custom-element',
styleUrl: 'my-custom-element.css',
shadow: true
})
export class MyCustomElement {
render() {
return (
<div>
<h1>Пример кастомного элемента</h1>
<p>Это кастомный элемент, созданный с использованием Stencil.</p>
</div>
);
}
}
Атрибуты позволяют передавать данные в кастомный элемент через
HTML-разметку. В Stencil для работы с атрибутами используются
декораторы. Атрибуты компонента могут быть связан с его внутренними
свойствами через декоратор @Prop. Стандартное использование
атрибутов позволяет гибко управлять состоянием компонента, например:
import { Component, Prop, h } from '@stencil/core';
@Component({
tag: 'user-card',
styleUrl: 'user-card.css',
shadow: true
})
export class UserCard {
@Prop() name: string;
@Prop() age: number;
render() {
return (
<div>
<h2>{this.name}</h2>
<p>Возраст: {this.age}</p>
</div>
);
}
}
Теперь можно использовать компонент <user-card> в
HTML-разметке и передавать ему значения:
<user-card name="Иван" age="30"></user-card>
Stencil автоматически отслеживает изменения в значениях атрибутов и обновляет рендеринг компонента, что делает работу с атрибутами простым и эффективным процессом.
Компоненты Stencil могут генерировать и слушать события. Это
позволяет интегрировать их в более сложные механизмы взаимодействия
между элементами. События создаются с помощью декоратора
@Event, а для их прослушивания используется обычный
механизм работы с событиями DOM. Рассмотрим пример создания и
прослушивания события:
import { Component, Event, EventEmitter, h } from '@stencil/core';
@Component({
tag: 'my-button',
styleUrl: 'my-button.css',
shadow: true
})
export class MyButton {
@Event() clicked: EventEmitter;
handleClick() {
this.clicked.emit({ message: 'Кнопка была нажата!' });
}
render() {
return (
<button onCl ick={() => this.handleClick()}>Нажми меня</button>
);
}
}
В этом примере создается событие clicked, которое будет
отправляться каждый раз, когда пользователь кликает на кнопку. Чтобы
слушать это событие, можно добавить следующий код:
<my-button onclic ked="handleButtonClick"></my-button>
<script>
function handleButtonClick(event) {
console.log(event.detail.message);
}
</script>
Stencil поддерживает использование Shadow DOM,
который позволяет инкапсулировать стиль и структуру компонента,
предотвращая их воздействие на внешний контекст. Включение Shadow DOM
для компонента можно настроить через параметр shadow в
декораторе @Component. Это дает возможность избежать
конфликтов стилей между компонентами.
Включение Shadow DOM в Stencil:
@Component({
tag: 'my-shadow-component',
styleUrl: 'my-shadow-component.css',
shadow: true
})
export class MyShadowComponent {
render() {
return (
<div>
<h2>Текст в Shadow DOM</h2>
</div>
);
}
}
С помощью Shadow DOM можно полностью изолировать стили и структуру компонента от окружающего контекста, что полезно при разработке модульных и независимых компонентов.
Stencil позволяет добавлять стили к компонентам с помощью обычных
CSS-файлов, а также с использованием CSS-переменных и стилевых
инкапсуляций. Для стилей, применяемых внутри компонента, используется
параметр styleUrl, который позволяет указать путь к
CSS-файлу. Также можно использовать scoped стили, которые
будут применяться только к компоненту, если включен режим Shadow
DOM.
Пример:
@Component({
tag: 'my-styled-component',
styleUrl: 'my-styled-component.css',
shadow: true
})
export class MyStyledComponent {
render() {
return (
<div>
<h1>Стильный компонент</h1>
</div>
);
}
}
При этом в my-styled-component.css могут быть определены
локальные стили, которые будут применяться только к элементам внутри
этого компонента.
Один из важных аспектов Stencil — это его способность интегрироваться с другими фреймворками. Созданные компоненты можно использовать в любых фреймворках, таких как React, Angular, Vue или даже в чистом JavaScript. Stencil автоматически генерирует соответствующие оболочки для использования компонентов в этих фреймворках, что позволяет строить кросс-фреймворк-приложения.
Для интеграции с React, например, можно использовать следующий код:
import { Component, Prop, h } from '@stencil/core';
@Component({
tag: 'my-react-component',
styleUrl: 'my-react-component.css',
shadow: true
})
export class MyReactComponent {
@Prop() title: string;
render() {
return <h1>{this.title}</h1>;
}
}
После сборки компонента с помощью Stencil, его можно будет использовать в React-приложении как обычный компонент:
import React from 'react';
import { render } from 'react-dom';
import 'my-react-component';
const App = () => (
<my-react-component title="Привет, мир!"></my-react-component>
);
render(<App />, document.getElementById('root'));
Stencil позаботится о том, чтобы компонент работал корректно и в других фреймворках.
Использование кастомных элементов в Stencil открывает широкие возможности для создания высокопроизводительных, инкапсулированных и повторно используемых компонентов. Система атрибутов, событий, поддержки Shadow DOM и интеграции с другими фреймворками позволяет разработчикам легко строить модульные и масштабируемые веб-приложения.