Компонентная архитектура приложений

Preact — это лёгкий и высокопроизводительный JavaScript-фреймворк для создания интерфейсов, совместимый с API React. Его ключевое преимущество заключается в компактном размере и высокой скорости рендеринга при использовании компонентной архитектуры. Компоненты в Preact являются строительными блоками приложения, объединяя логику, разметку и состояние в единый объект.


Компоненты: функции и классы

В Preact можно создавать компоненты двумя способами: функциональными компонентами и классовыми компонентами.

Функциональные компоненты

Функциональные компоненты представляют собой простые функции, которые принимают props и возвращают JSX. Их преимущество — лёгкость и предсказуемость.

import { h } from 'preact';

function Button({ label, onClick }) {
  return <button onCl ick={onClick}>{label}</button>;
}

Ключевые моменты:

  • Props передаются в компонент сверху вниз.
  • Функции должны быть чистыми: одинаковые входные данные дают одинаковый результат.
  • Использование хуков (useState, useEffect) позволяет управлять состоянием и побочными эффектами.

Классовые компоненты

Классовые компоненты наследуются от Component и предоставляют более традиционный подход с методами жизненного цикла.

import { h, Component } from 'preact';

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  increment = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <p>{this.state.count}</p>
        <button onCl ick={this.increment}>Increment</button>
      </div>
    );
  }
}

Ключевые моменты:

  • Доступны методы жизненного цикла: componentDidMount, componentDidUpdate, componentWillUnmount.
  • Состояние хранится в объекте this.state, обновление через this.setState.
  • Используются реже, чем функциональные компоненты, за счёт хуков, но остаются актуальными для сложной логики.

Props и State

Props — это свойства, которые передаются компоненту извне. Они неизменяемы внутри компонента и служат для конфигурации и передачи данных между компонентами.

State — внутреннее состояние компонента, изменяемое с помощью useState или this.setState. State управляет динамическими изменениями интерфейса и реакцией на действия пользователя.

import { h } from 'preact';
import { useState } from 'preact/hooks';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>{count}</p>
      <button onCl ick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

Особенности:

  • Изменение state вызывает повторный рендер компонента.
  • Props и state могут комбинироваться для создания сложной логики отображения.

Жизненный цикл компонентов

Жизненный цикл управляет поведением компонентов от их создания до удаления. В Preact жизненный цикл классовых компонентов включает:

  • componentDidMount — вызывается после монтирования компонента в DOM.
  • componentDidUpdate — вызывается после обновления props или state.
  • componentWillUnmount — выполняется перед удалением компонента.

Функциональные компоненты используют хуки эффекта (useEffect) для реализации аналогичной логики:

import { h } from 'preact';
import { useEffect } from 'preact/hooks';

function Timer() {
  useEffect(() => {
    const interval = setInterval(() => console.log('tick'), 1000);
    return () => clearInterval(interval); // очистка при размонтировании
  }, []);

  return <p>Timer работает</p>;
}

Ключевой момент: массив зависимостей [] контролирует, когда выполняется эффект. Пустой массив означает, что эффект выполняется один раз при монтировании.


Вложенные компоненты и композиция

Компоненты Preact легко комбинируются для построения сложного интерфейса. Вложение компонентов позволяет повторно использовать логику и оформление.

function Card({ title, content }) {
  return (
    <div className="card">
      <h3>{title}</h3>
      <p>{content}</p>
    </div>
  );
}

function Dashboard() {
  return (
    <div>
      <Card title="Статистика" content="Данные за неделю" />
      <Card title="Новости" content="Последние события" />
    </div>
  );
}

Особенности композиции:

  • Каждый компонент инкапсулирует свою логику и стиль.
  • Легко тестировать и изменять отдельные части приложения.
  • Поддерживает контейнерные и презентационные компоненты, разделяя логику и отображение.

Контекст и глобальное состояние

Для передачи данных глубоко вниз по дереву компонентов используется Context. Он позволяет избежать «проброса» props через множество уровней.

import { h, createContext } from 'preact';
import { useContext } from 'preact/hooks';

const ThemeContext = createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>Button</button>;
}

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <ThemedButton />
    </ThemeContext.Provider>
  );
}

Ключевые моменты:

  • Provider задаёт значение контекста для всех вложенных компонентов.
  • useContext позволяет компоненту получать текущее значение.
  • Контекст упрощает управление глобальными настройками и состояниями.

Ключевые принципы компонентной архитектуры Preact

  1. Модульность — каждый компонент решает отдельную задачу.
  2. Повторное использование — компоненты легко применять в разных местах.
  3. Инкапсуляция — логика, стиль и структура компонента изолированы.
  4. Однонаправленный поток данных — props передаются сверху вниз, state управляет локальными изменениями.
  5. Предсказуемость и тестируемость — чистые компоненты проще отлаживать и покрывать тестами.

Компонентная архитектура Preact формирует основу современных интерфейсов, обеспечивая высокую производительность, гибкость и структурированность приложений.