В SvelteKit ключевым принципом является композиция компонентов. Это позволяет строить интерфейсы из маленьких, переиспользуемых блоков, обеспечивая гибкость и масштабируемость приложения. Каждый компонент инкапсулирует структуру, логику и стили, что облегчает поддержку и тестирование.
В контексте UI библиотек, таких как Svelte Material UI, Flowbite-Svelte или Skeleton, композиция реализуется через слоты, пропсы и контекст, что позволяет:
Слоты являются основным инструментом композиции в SvelteKit UI. Они позволяют вставлять вложенные элементы в шаблон компонента без жесткой привязки к структуре родителя.
<!-- Parent.svelte -->
<Card>
<Header slot="header">Заголовок карточки</Header>
<Content slot="content">Основной текст</Content>
</Card>
<!-- Card.svelte -->
<div class="card">
<div class="card-header">
<slot name="header"></slot>
</div>
<div class="card-content">
<slot name="content"></slot>
</div>
</div>
В этом примере Card выступает оберткой,
которая определяет стиль и разметку, а содержимое определяется через
слоты. Такой подход поддерживает повторное использование
компонентов и делает структуру приложения предсказуемой.
Композиция компонентов требует гибкого механизма для передачи информации. В SvelteKit это достигается через пропсы, события и контекст.
<Button variant="primary" disabled={isLoading}>Отправить</Button>
createEventDispatcher:<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
function handleClick() {
dispatch('submit', { success: true });
}
</script>
<button on:click={handleClick}>Submit</button>
<!-- Provider.svelte -->
<script context="module">
import { setContext } from 'svelte';
const theme = { color: 'blue' };
setContext('theme', theme);
</script>
<slot></slot>
<!-- Child.svelte -->
<script>
import { getContext } from 'svelte';
const theme = getContext('theme');
</script>
<p style="color: {theme.color}">Текст с темой</p>
UI библиотеки для SvelteKit предлагают собственные паттерны для построения сложных интерфейсов:
<Modal>
<ModalHeader>Заголовок</ModalHeader>
<ModalBody>Содержимое модального окна</ModalBody>
<ModalFooter>
<Button>Закрыть</Button>
</ModalFooter>
</Modal>
Modal управляет логикой открытия/закрытия, а дочерние
компоненты отвечают за визуальные части.
<Dropdown let:item>
<button>{item.label}</button>
</Dropdown>
В этом паттерне Dropdown управляет состоянием открытого
списка, а внешний компонент контролирует отображение каждого
элемента.
<Tabs>
<Tab slot="tab" title="Первый">Контент первой вкладки</Tab>
<Tab slot="tab" title="Вторая">Контент второй вкладки</Tab>
</Tabs>
<!-- Управляемый Input -->
<Input bind:value={inputValue} />
<!-- Самостоятельный Input -->
<Input />
Библиотеки предоставляют оба варианта для повышения гибкости.
Композиция компонентов тесно связана с управлением состоянием. Основные подходы:
<script>
import { writable } from 'svelte/store';
export const count = writable(0);
</script>
<script>
import { count } from './store.js';
</script>
<button on:click={() => $count++}>Увеличить</button>
<p>Значение: {$count}</p>
Context API — для передачи настроек и глобальных данных без необходимости пробрасывать через каждый компонент.
Derived и Readable Stores — позволяют создавать вычисляемое состояние, что особенно полезно для сложных UI, таких как фильтры, таблицы и дашборды.
SvelteKit UI библиотеки используют реактивность для автоматического обновления UI при изменении данных. В комбинации с композиционными паттернами это позволяет строить динамичные и отзывчивые интерфейсы без лишней сложности.
<script>
let selectedTab = 0;
</script>
<Tabs bind:selected={selectedTab}>
<Tab title="Первый">Контент 1</Tab>
<Tab title="Второй">Контент 2</Tab>
</Tabs>
<p>Выбрана вкладка: {selectedTab + 1}</p>
Эти паттерны образуют основу построения интерфейсов в SvelteKit UI библиотеках, обеспечивая чистоту кода, предсказуемость поведения и высокую адаптивность компонентов.