Component vs FlowModel

При разработке плагинов NocoBase для написания фронтенд-UI существует два способа: обычные React-компоненты и FlowModel. Это не взаимозаменяемые подходы — FlowModel представляет собой слой обёртки над React-компонентом, добавляющий возможности визуальной конфигурации.

Обычно Вам не нужно долго раздумывать. Задайте себе один вопрос:

Должен ли этот компонент появляться в меню «Добавить блок / поле / действие» NocoBase, чтобы пользователь мог визуально настраивать его в интерфейсе?

  • Не должен → используйте обычный React-компонент, это стандартная разработка на React
  • Должен → используйте обёртку FlowModel

Решение по умолчанию: React-компонент

В большинстве сценариев плагинов достаточно обычных React-компонентов. Например:

  • Регистрация отдельной страницы (страница настроек плагина, пользовательская страница маршрута)
  • Написание модального окна, формы, списка и других внутренних компонентов
  • Создание утилитарного UI-компонента

В таких сценариях Вы пишете компоненты на React + Antd, через useFlowContext() получаете доступ к возможностям контекста NocoBase (запросы, интернационализация и т.д.) — это ничем не отличается от обычной фронтенд-разработки.

import { useFlowContext } from '@nocobase/flow-engine';

export default function MySettingsPage() {
  const ctx = useFlowContext();

  return (
    <div>
      <h2>{ctx.t('Plugin settings')}</h2>
      {/* 普通 React 组件,不需要 FlowModel */}
    </div>
  );
}

Подробное использование см. в Разработка Component-компонентов.

Когда использовать FlowModel

Используйте FlowModel, когда Ваш компонент должен соответствовать следующим условиям:

  1. Появляется в меню: должен быть добавляем пользователем через меню «Добавить блок», «Добавить поле», «Добавить действие»
  2. Поддерживает визуальную конфигурацию: пользователь может в интерфейсе кликать по пунктам конфигурации, чтобы изменить свойства компонента (например, изменить заголовок, переключить режим отображения)
  3. Конфигурация должна сохраняться: настройки пользователя должны сохраняться, чтобы при следующем открытии страницы они были доступны

Проще говоря, FlowModel решает проблему «сделать компонент конфигурируемым и сохраняемым». Если Вашему компоненту эти возможности не нужны, FlowModel Вам не понадобится.

Связь между ними

FlowModel не предназначен для «замены» React-компонентов. Это абстракция поверх React-компонента:

React-компонент: отвечает за рендеринг UI
    ↓ обёртка
FlowModel: управляет источником props, панелью конфигурации, сохранением конфигурации

В методе render() FlowModel пишется обычный React-код. Разница в том, что props обычного компонента жёстко заданы или передаются от родительского компонента, а props FlowModel генерируются динамически через Flow (процесс конфигурации).

На самом деле, по базовой структуре они очень похожи:

// React 组件
class MyComponent extends React.Component {
  render() {
    return <div>Hello</div>;
  }
}

// FlowModel
class HelloModel extends FlowModel {
  render() {
    return <div>Hello</div>;
  }
}

Однако способы управления у них совершенно разные. React-компоненты формируют дерево компонентов через вложенность JSX — это дерево UI-рендеринга во время выполнения. FlowModel управляется FlowEngine и формирует дерево моделей — сохраняемое, динамически регистрируемое логическое структурное дерево, в котором отношения родитель-потомок управляются явно через setSubModel / addSubModel. Оно подходит для построения структур, требующих конфигурируемого управления, таких как блоки страницы, потоки операций и модели данных.

Сравнение возможностей

С более технической точки зрения, различия между ними:

ВозможностьReact-компонентFlowModel
Рендеринг UIrender()render()
Управление состояниемВстроенные state / setStateУправление через props и структуру дерева моделей
Жизненный циклconstructor, componentDidMount, componentWillUnmountonInit, onMount, onUnmount
Реакция на изменение входаcomponentDidUpdateonBeforeAutoFlows, onAfterAutoFlows
Обработка ошибокcomponentDidCatchonAutoFlowsError
Дочерние компонентыВложенность JSXsetSubModel / addSubModel для явной установки дочерних моделей
Динамическое поведениеПривязка событий, обновление состоянияРегистрация и диспетчеризация Flow
СохранениеНет встроенного механизмаmodel.save() и т.д., с интеграцией с бэкендом
Многократное использованиеНужно обрабатывать вручнуюcreateFork — например, для каждой строки таблицы
Управление движкомНетУнифицированная регистрация, загрузка и управление через FlowEngine

Если Вы знакомы с жизненным циклом React, жизненный цикл FlowModel легко сопоставить — onInit соответствует constructor, onMount соответствует componentDidMount, onUnmount соответствует componentWillUnmount.

Кроме того, FlowModel предоставляет некоторые возможности, которых нет у React-компонентов:

  • registerFlow — регистрация Flow, определение процесса конфигурации
  • applyFlow / dispatchEvent — выполнение или запуск Flow
  • openFlowSettings — открытие панели настроек шага Flow
  • save / saveStepParams() — сохранение конфигурации модели
  • createFork — многократный рендеринг логики одной модели (например, для каждой строки таблицы)

Эти возможности являются основой для поддержки опыта «визуальной конфигурации». Если Ваш сценарий не предполагает визуальную конфигурацию, не нужно об этом беспокоиться. Подробное использование см. в полной документации FlowEngine.

Сравнение сценариев

СценарийРешениеПричина
Страница настроек плагинаReact-компонентОтдельная страница, не нужно появляться в меню конфигурации
Утилитарное модальное окноReact-компонентВнутренний компонент, визуальная конфигурация не нужна
Пользовательский блок таблицы данныхFlowModelДолжен появиться в меню «Добавить блок», пользователь может настроить источник данных
Пользовательский компонент отображения поляFlowModelДолжен появиться в конфигурации поля, пользователь может выбрать способ отображения
Пользовательская кнопка действияFlowModelДолжна появиться в меню «Добавить действие»
Обёртка компонента графика для использования в блокеReact-компонентСам график — внутренний компонент, его вызывает блок FlowModel

Постепенное внедрение

Когда Вы не уверены, сначала реализуйте функциональность через React-компонент. После того как подтвердится необходимость в возможностях визуальной конфигурации, оберните его в FlowModel — это рекомендуемый постепенный подход. Большие блоки управляйте через FlowModel, внутренние детали реализуйте через React-компоненты, используя их совместно.

Связанные ссылки