Fresh — современный фреймворк для разработки веб-приложений на Deno, который ориентирован на минимализм и рендеринг на сервере. Компоненты во Fresh выполняют роль строительных блоков интерфейса, обеспечивая повторное использование кода, разделение логики и представления, а также интеграцию с серверной частью приложения. Рассмотрим ключевые паттерны работы с компонентами.
В Fresh компоненты создаются как функции, которые возвращают JSX. Они могут принимать props для передачи данных и управлять отображением интерфейса. Такой подход позволяет легко комбинировать компоненты и создавать динамические интерфейсы.
interface ButtonProps {
label: string;
onClick?: () => void;
}
export default function Button({ label, onClick }: ButtonProps) {
return (
<button onCl ick={onClick} class="px-4 py-2 bg-blue-500 text-white rounded">
{label}
</button>
);
}
Особенности:
Компоненты легко вкладываются друг в друга, образуя сложные интерфейсы. Передача пропсов позволяет создавать универсальные элементы.
interface CardProps {
title: string;
description: string;
}
export default function Card({ title, description }: CardProps) {
return (
<div class="p-4 border rounded shadow-md">
<h2 class="text-xl font-bold">{title}</h2>
<p>{description}</p>
</div>
);
}
export function App() {
return (
<div class="space-y-4">
<Card title="Card 1" description="Описание первой карточки" />
<Card title="Card 2" description="Описание второй карточки" />
</div>
);
}
Преимущества вложенных компонентов:
Fresh поддерживает концепцию островов
интерактивности (islands), где части страницы могут быть
интерактивными без полной нагрузки на клиент. Состояние компонентов
можно хранить с помощью хука useState из Preact, так как
Fresh использует Preact для клиентской интерактивности.
import { useState } from "preact/hooks";
export default function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Счётчик: {count}</p>
<button onCl ick={() => setCount(count + 1)}>Увеличить</button>
</div>
);
}
Особенности работы состояния:
Разделение логики и представления повышает читаемость и переиспользуемость кода. В Fresh это реализуется через разделение компонентов на контейнеры (логика, загрузка данных) и презентационные компоненты (рендер UI).
// Контейнер
import CardList from "./CardList.tsx";
export default async function CardContainer() {
const response = await fetch("https://api.example.com/cards");
const cards = await response.json();
return <CardList cards={cards} />;
}
// Презентационный компонент
interface CardListProps {
cards: { title: string; description: string }[];
}
export default function CardList({ cards }: CardListProps) {
return (
<div class="grid grid-cols-3 gap-4">
{cards.map(card => (
<div key={card.title} class="p-4 border rounded shadow">
<h3>{card.title}</h3>
<p>{card.description}</p>
</div>
))}
</div>
);
}
Преимущества подхода:
Render props позволяют передавать функцию для кастомного рендеринга части компонента, обеспечивая максимальную гибкость. В Fresh этот паттерн часто применяется для сложных UI-элементов и динамических интерфейсов.
interface ListProps<T> {
items: T[];
renderItem: (item: T) => JSX.Element;
}
export function List<T>({ items, renderItem }: ListProps<T>) {
return <ul>{items.map(item => <li>{renderItem(item)}</li>)}</ul>;
}
// Использование
<List
items={[1, 2, 3]}
renderItem={num => <span>Элемент {num}</span>}
/>
Особенности:
Fresh поддерживает динамический импорт компонентов, что полезно для условного рендеринга и оптимизации загрузки.
let DynamicComponent;
if (someCondition) {
DynamicComponent = (await import("./SpecialComponent.tsx")).default;
}
export default function Page() {
return (
<div>
{DynamicComponent ? <DynamicComponent /> : <p>Обычное содержимое</p>}
</div>
);
}
Преимущества:
Основные паттерны компонентов во Fresh обеспечивают:
Эти подходы создают основу для построения масштабируемых и производительных приложений с серверным рендерингом и минимальной клиентской нагрузкой.