Основные концепции и терминология

Виртуальный DOM и его роль

В основе Inferno лежит концепция виртуального DOM (Virtual DOM). Виртуальный DOM представляет собой легковесное дерево JavaScript-объектов, которое описывает структуру интерфейса. Основная задача виртуального DOM — минимизировать количество операций с реальным DOM, который является медленным и ресурсоёмким. При изменении состояния приложения Inferno сравнивает текущее и новое виртуальные деревья (diffing), а затем обновляет только изменённые части реального DOM. Этот подход обеспечивает высокую производительность даже при сложных интерфейсах.

JSX и элементы Inferno

JSX — это синтаксис, позволяющий описывать структуру интерфейса в виде похожего на HTML кода. В Inferno JSX компилируется в вызовы функции Inferno.createVNode, которая создаёт виртуальные узлы (vnode). Каждое использование JSX создаёт объект с типом элемента, его свойствами (props) и дочерними элементами. Пример структуры vnode:

const vnode = {
  type: 'div',
  props: { className: 'container' },
  children: [
    { type: 'span', props: {}, children: ['Текст'] }
  ]
};

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

  • type — тип элемента (div, span или компонент).
  • props — свойства элемента (className, onClick и другие атрибуты).
  • children — дочерние узлы, массив виртуальных узлов или текстовых значений.

Компоненты и их классификация

Inferno поддерживает два основных типа компонентов: функциональные и классовые.

  1. Функциональные компоненты — это функции, принимающие props и возвращающие JSX. Они не имеют собственного состояния, хотя можно использовать хуки для управления состоянием и жизненным циклом.
function Button({ label, onClick }) {
  return <button onCl ick={onClick}>{label}</button>;
}
  1. Классовые компоненты наследуются от Inferno.Component и обладают внутренним состоянием (state). Методы жизненного цикла включают componentDidMount, componentDidUpdate, componentWillUnmount.
class Counter extends Inferno.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

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

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

Props и state

Props — это свойства, передаваемые компоненту извне. Они неизменны внутри компонента. State — это внутреннее состояние компонента, которое может изменяться с помощью метода setState (для классовых компонентов) или хуков (для функциональных).

Ключевое отличие:

  • Props: управление извне, статичны для компонента.
  • State: управление внутри компонента, динамично.

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

Классовые компоненты Inferno имеют набор методов жизненного цикла, определяющих этапы существования компонента:

  • constructor — инициализация состояния.
  • componentWillMount — подготовка перед монтированием.
  • componentDidMount — действия после добавления компонента в DOM.
  • shouldComponentUpdate — решение о перерисовке.
  • componentDidUpdate — обработка изменений после обновления.
  • componentWillUnmount — очистка ресурсов перед удалением компонента.

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

События и их обработка

Inferno использует синтетическую систему событий, аналогичную React. События назначаются через свойства элементов (onClick, onChange, onInput) и обрабатываются через единый механизм делегирования. Это позволяет уменьшить количество слушателей в DOM и повышает производительность.

function InputField({ onChange }) {
  return <input type="text" onIn put={onChange} />;
}

Ключи (keys) и оптимизация рендеринга

При рендеринге списков элементов важно использовать ключи (key) для уникальной идентификации каждого элемента. Ключи помогают Inferno корректно сопоставлять виртуальные узлы при обновлении интерфейса, минимизируя количество изменений в реальном DOM.

const items = ['яблоко', 'банан', 'груша'];
const list = items.map((item, index) => <li key={index}>{item}</li>);

Хуки

Inferno поддерживает хуки функциональных компонентов для управления состоянием и побочными эффектами:

  • useState — хранение локального состояния.
  • useEffect — выполнение побочных эффектов после рендера.
  • useRef — хранение ссылок на DOM-элементы или данные между рендерами.
  • useMemo и useCallback — оптимизация вычислений и функций.

Пример использования useState:

import { useState } from 'inferno-hooks';

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

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

Порталы и рендер вне корня

Inferno позволяет рендерить компоненты вне основного корня приложения с помощью порталов. Это особенно полезно для модальных окон и уведомлений, когда DOM-структура требует размещения элемента в другом месте документа.

import { createPortal } from 'inferno';

function Modal({ children }) {
  const modalRoot = document.getElementById('modal-root');
  return createPortal(<div className="modal">{children}</div>, modalRoot);
}

Контекст (Context API)

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

import { createContext } from 'inferno';

const ThemeContext = createContext('light');

function ThemedButton() {
  return (
    <ThemeContext.Consumer>
      {theme => <button className={theme}>Кнопка</button>}
    </ThemeContext.Consumer>
  );
}

Рендеринг и гидратация

Inferno поддерживает как клиентский рендеринг (render), так и серверный с гидратацией (hydrate). Гидратация используется для оживления предварительно отрендеренного HTML на сервере, что позволяет сохранять состояние и обработчики событий на клиенте без полной перерисовки.

import { render, hydrate } from 'inferno';
render(<App />, document.getElementById('root'));
hydrate(<App />, document.getElementById('root'));

Оптимизация производительности

Основные подходы к оптимизации:

  • Использование ключей при рендеринге списков.
  • Избегание лишних обновлений через shouldComponentUpdate или хуки useMemo, useCallback.
  • Минимизация операций с реальным DOM с помощью виртуального DOM.
  • Профилирование и измерение производительности при рендеринге больших списков и сложных компонентов.

Эти концепции составляют фундамент для построения эффективных и масштабируемых приложений на Inferno, обеспечивая сочетание высокой скорости, удобного синтаксиса и гибкой архитектуры компонентов.