Порядок выполнения хуков

Порядок выполнения хуков в Chart.js определяется жизненным циклом графика и тем, на каком этапе происходит подготовка данных, расчёт геометрии и отрисовка на canvas. Плагины и внутренние механизмы библиотеки используют строго фиксированную последовательность вызовов, что позволяет предсказуемо вмешиваться в процесс рендеринга.

Жизненный цикл графика делится на несколько крупных фаз:

  • инициализация экземпляра
  • обновление данных и конфигурации
  • расчёт макета
  • отрисовка элементов
  • завершение кадра

Каждая фаза содержит собственные хуки, которые вызываются в строго определённом порядке. Нарушение логики последовательности невозможно, так как Chart.js управляет вызовами централизованно через ядро Animator и систему плагинов.

Хуки инициализации

На этапе создания экземпляра графика выполняется следующий порядок:

  1. beforeInit
  2. внутренняя инициализация структуры данных
  3. afterInit

beforeInit вызывается до того, как создаются масштабы, элементы данных и layout. На этом этапе допустимо модифицировать входной конфиг, добавлять или удалять плагины, подменять наборы данных.

afterInit срабатывает после завершения базовой подготовки структуры графика. В этот момент уже существуют scales, datasets и элементы представления, но рендер ещё не начался.

Хуки обновления данных

Обновление графика инициируется при изменении данных, опций или внешнего состояния. Последовательность выглядит следующим образом:

  1. beforeUpdate
  2. пересчёт внутренних структур
  3. afterUpdate

beforeUpdate используется для вмешательства в процесс до перерасчёта метрик. Важно, что изменения, сделанные здесь, влияют на весь последующий pipeline.

После перерасчёта данных и пересборки элементов вызывается afterUpdate. На этом этапе уже готовы новые координаты, но отрисовка ещё не выполнена.

Хуки макета

Фаза layout отвечает за распределение пространства и вычисление размеров элементов.

Порядок выполнения:

  1. beforeLayout
  2. расчёт layout engine
  3. afterLayout

beforeLayout позволяет вмешиваться в размеры осей, padding, area chart bounds. Изменения здесь могут привести к перерасчёту геометрии.

afterLayout фиксирует результат вычислений макета. Все элементы получают финальные размеры, но canvas ещё не рисуется.

Хуки обновления наборов данных

Отдельная подфаза связана с пересчётом dataset-ов:

  1. beforeDatasetsUpdate
  2. обновление элементов dataset
  3. afterDatasetsUpdate

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

beforeDatasetsUpdate позволяет вмешаться до пересчёта элементов линий, баров, точек и других визуальных примитивов.

afterDatasetsUpdate фиксирует результат подготовки наборов данных перед отрисовкой.

Хуки отрисовки

Самая сложная и важная часть жизненного цикла связана с отрисовкой на canvas. Здесь порядок строго детерминирован:

  1. beforeDraw
  2. отрисовка фона и базовых слоёв
  3. beforeDatasetsDraw
  4. отрисовка datasets
  5. afterDatasetsDraw
  6. afterDraw

beforeDraw вызывается перед началом любой графической операции. В этот момент canvas уже очищен, но ничего ещё не нарисовано. Этот хук часто используется для кастомного фона или подготовительных эффектов.

beforeDatasetsDraw срабатывает непосредственно перед отрисовкой всех dataset-ов. Именно здесь находятся линии, бары, точки и другие основные элементы графика.

afterDatasetsDraw вызывается сразу после завершения отрисовки данных, но до финальных декоративных слоёв.

afterDraw завершает полный цикл рендеринга. В этот момент canvas полностью готов и может быть дополнен внешними слоями, аннотациями или сторонними эффектами.

Дополнительные системные хуки

Помимо основных фаз существуют вспомогательные события, которые встроены в жизненный цикл:

  • resize — вызывается при изменении размеров контейнера
  • destroy — вызывается при удалении экземпляра графика

resize запускает частичный пересчёт layout и перерисовку без полной переинициализации. Порядок выполнения внутри resize повторяет часть pipeline: layout → datasets update → draw.

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

Приоритет и последовательность плагинов

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

  • плагины, зарегистрированные раньше, получают вызовы раньше
  • внутри одного хука порядок фиксирован и не зависит от типа плагина

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

Взаимосвязь хуков внутри одного кадра

Полный цикл одного обновления графика объединяет все фазы:

  • инициализация или обновление состояния
  • пересчёт данных
  • вычисление layout
  • подготовка dataset-ов
  • отрисовка слоёв
  • финализация кадра

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

Особенности синхронного выполнения

Все хуки выполняются синхронно в рамках одного call stack. Асинхронные операции внутри хуков не блокируют сам Chart.js pipeline, но могут привести к рассинхронизации состояния, если изменяют данные после завершения текущего кадра.

Из-за синхронной природы выполнения порядок строго линейный:

  • нет параллельных фаз
  • нет переопределения последовательности
  • нет повторного входа в уже завершённый этап без явного update вызова

Влияние конфигурации на порядок выполнения

Конфигурация графика не меняет порядок хуков, но влияет на их количество и глубину:

  • включённые анимации добавляют дополнительные промежуточные состояния внутри draw
  • сложные scales увеличивают длительность layout-фазы
  • кастомные элементы расширяют datasets update фазу

Структура pipeline остаётся неизменной, изменяется только объём вычислений внутри каждого этапа