NocoBase 插件开发选型指南:Component 与 FlowModel 的能力边界与生命周期对比
2026/9/17 1:18:45 网站建设 项目流程

NocoBase 插件开发选型指南:Component 与 FlowModel 的能力边界与生命周期对比

【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase

在 NocoBase 插件开发中,前端 UI 的编写存在两条路径:普通 React 组件FlowModel。本文以 Component vs FlowModel 为骨架,结合 FlowEngine 源码与配套文档,讲清两者"谁替代谁"的关系、能力差异、生命周期映射以及渐进式采用的实战策略。读完你将能准确判断"什么时候写 React 组件、什么时候用 FlowModel 包装",并理解可视化配置能力在底层是如何由模型树驱动的。

核心判断:一个问题的选型标准

两者不是互相替代的关系——FlowModel 是在 React 组件之上的一层封装,它给组件加上了可视化配置的能力。在动手写代码之前,只需要问自己一个问题:

这个组件需要出现在 NocoBase 的「添加区块 / 字段 / 操作」菜单里,让用户在界面上进行可视化配置吗?

  • 不需要→ 用普通 React 组件,就是标准的 React 开发;
  • 需要→ 用 FlowModel 包装。

这个判断标准贯穿整个插件开发过程,也是 NocoBase 对"组件是否可配置"这一边界问题的官方答案。

默认方案:普通 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 组件开发 给出了更完整的落地姿势,核心有三点:

  1. 路由挂载的页面组件就是普通 React 组件。在插件的load()里通过this.router.add()注册路由即可挂载到 URL(见 Router 路由)。
  2. 状态管理推荐observable+observer,而非useState。二者都从@nocobase/flow-engine导入:用observable.deep()创建响应式对象,用observer()包裹组件。好处是直接修改对象属性即可触发更新(无需setState)、自动依赖收集(组件只在用到的属性变化时重渲染),并且与 NocoBase 底层(FlowModel、FlowContext)的响应式机制保持一致:
import React from 'react'; import { Input } from 'antd'; import { observable, observer } from '@nocobase/flow-engine'; const state = observable.deep({ text: '', }); const DemoPage = observer(() => { return ( <div> <Input placeholder="输入点什么..." value={state.text} onChange={(e) => { state.text = e.target.value; }} /> {state.text && <div style={{ marginTop: 8 }}>你输入了:{state.text}</div>} </div> ); }); export default DemoPage;
  1. useFlowContext()是连接 NocoBase 能力的入口,返回ctx对象,常用能力包括:
import { useFlowContext } from '@nocobase/flow-engine'; export default function MyPage() { const ctx = useFlowContext(); // ctx.api — 发请求 // ctx.t — 国际化 // ctx.router — 路由导航 // ctx.logger — 日志 }
  • 发请求:ctx.api.request({ url: 'users:list', method: 'get' }),用法与 Axios 一致;
  • 国际化:ctx.t('Save success', { ns: '@my-project/plugin-hello' }),可指定命名空间;
  • 路由导航:ctx.router.navigate('/some-page'),并通过ctx.route.params/ctx.route.name读取当前路由参数与路由名。

完整能力清单见 Context 上下文。

什么时候用 FlowModel

当组件满足以下三个条件时,就该用 FlowModel:

  1. 出现在菜单里:需要让用户通过「添加区块」「添加字段」「添加操作」菜单来添加;
  2. 支持可视化配置:用户可以在界面上点击配置项来修改组件的属性(比如修改标题、切换显示模式);
  3. 配置需要持久化:用户的配置需要保存下来,下次打开页面时还在。

简单来说,FlowModel 解决的是"让组件可配置、可持久化"的问题。如果你的组件不需要这些能力,就不需要用它。

从源码看,FlowEngine(流引擎)正是驱动 NocoBase 界面上区块、字段、操作按钮渲染、配置面板与配置持久化的核心引擎,见 FlowEngine 概述。对插件开发者而言,FlowEngine 提供两个核心概念:

  • FlowModel— 可配置的组件模型,负责渲染 UI 和管理 props;
  • Flow— 配置流程,定义组件的配置面板和数据处理逻辑。

二者的关系:不是替代,而是包装

FlowModel 不是用来"替代" React 组件的,它是在 React 组件之上的一层抽象:

React 组件:负责渲染 UI ↓ 包装 FlowModel:管理 props 来源、配置面板、配置持久化

一个 FlowModel 的render()(或其子类重写的renderComponent())方法里,写的就是普通的 React 代码。区别在于:普通组件的 props 是写死的或从父组件传入的,FlowModel 的 props 是通过 Flow(配置流程)动态生成的

实际上,两者在基本结构上很相似:

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

组件树 vs 模型树

不过它们的管理方式完全不同:

  • React 组件靠 JSX 嵌套形成组件树——这是运行时的 UI 渲染树;
  • FlowModel则由 FlowEngine 管理,形成模型树——一棵可持久化、可动态注册的逻辑结构树,通过setSubModel/addSubModel显式控制父子关系,适合构建页面区块、操作流、数据模型这类需要配置化管理的结构。

在源码中,flowModel.tsx 的addSubModel会通过flowEngine.createModel创建子模型并设置parentIdsubKey,将子模型挂到parent.subModels[subKey]数组,同时向模型自身事件总线与引擎级事件总线(model:subModel:added)发射变更事件;而setSubModel则用于设置单一(非数组)的子模型。模型树上的父子关系由此被显式、可持久化地管理起来,这正是 FlowModel 与 React 组件树最本质的差异。

能力对比:一张表看清差异

从更技术的角度看二者的差异:

能力React 组件FlowModel
渲染 UIrender()render()
状态管理内建state/setState通过props和模型树结构管理
生命周期constructorcomponentDidMountcomponentWillUnmountonInitonMountonUnmount
响应输入变化componentDidUpdateonBeforeAutoFlowsonAfterAutoFlows
错误处理componentDidCatchonAutoFlowsError
子组件JSX 嵌套setSubModel/addSubModel显式设置子模型
动态行为事件绑定、状态更新注册和派发 Flow
持久化无内建机制model.save()等,和后端打通
多实例复用需手动处理createFork——比如表格的每一行
引擎管理由 FlowEngine 统一注册、加载、管理

生命周期映射

如果你熟悉 React 的生命周期,FlowModel 的生命周期很容易映射过来:

  • onInit对应constructor
  • onMount对应componentDidMount
  • onUnmount对应componentWillUnmount

这些钩子在源码中均有完整实现与测试佐证:onInit定义于 flowModel.tsx(由构造函数在属性定义完成后调度调用,子类可覆盖并super.onInit(options));onMount/onUnmount定义于同一文件,且由FlowModelRenderer在挂载/卸载时调用,测试用例见 flowModel.test.ts,覆盖了"作为渲染目标"与"作为子模型"两种调用场景;onInit的父子调用顺序(父先于子)则在 flow-model-oninit.test.ts 中有明确断言。

FlowModel 的独有能力

另外,FlowModel 还提供了一些 React 组件没有的能力:

  • registerFlow— 注册 Flow,定义配置流程;
  • applyFlow/dispatchEvent— 执行或触发 Flow;
  • openFlowSettings— 打开 Flow 步骤的设置面板;
  • save/saveStepParams()— 持久化模型配置;
  • createFork— 一个模型逻辑被复用渲染多次(比如表格每行)。

这些能力全部在 flowModel.tsx 中有真实实现:registerFlow同时提供静态与实例两种形态(L637、L681);applyFlow/dispatchEvent经由flowEngine.executor执行(L852、L901);createFork用于生成逻辑复用的 fork 模型(L1384),其多实例语义在 forkFlowModel.ts 中实现;savesaveStepParams负责配置持久化(L1451、L1458);openFlowSettings负责打开 Flow 步骤的设置面板(L1658)。

这些能力是支撑「可视化配置」体验的基础。如果你的场景不涉及可视化配置,不需要关心它们。完整参考见 FlowEngine 完整文档。

场景对照:什么场景选什么方案

场景方案原因
插件设置页React 组件独立页面,不需要出现在配置菜单里
工具类弹窗React 组件内部组件,不需要可视化配置
自定义数据表格区块FlowModel需要出现在「添加区块」菜单,用户可以配置数据源
自定义字段展示组件FlowModel需要出现在字段配置里,用户可以选择展示方式
自定义操作按钮FlowModel需要出现在「添加操作」菜单里
封装一个图表组件给区块用React 组件图表本身是内部组件,由 FlowModel 的区块来调用它

FlowModel 实战速览:三步走 + 基类选择

为了让选型结论落到实处,这里结合 FlowEngine 概述 与 区块扩展,给出 FlowModel 从创建到注册的完整路径。

1. 继承基类,实现 renderComponent

// models/HelloBlockModel.tsx import React from 'react'; import { BlockModel } from '@nocobase/client-v2'; import { tExpr } from '@nocobase/flow-engine'; export class HelloBlockModel extends BlockModel { renderComponent() { return ( <div> <h3>Hello FlowEngine!</h3> <p>这是一个自定义区块。</p> </div> ); } } // define() 设置菜单里的显示名 HelloBlockModel.define({ label: tExpr('Hello block'), });

renderComponent()就是这个模型的渲染方法,类似 React 组件的render()tExpr()用于延迟翻译——因为define()在模块加载时就执行了,此时 i18n 还没初始化。

2. 在 Plugin 里注册

// plugin.tsx import { Plugin } from '@nocobase/client-v2'; export class MyPlugin extends Plugin { async load() { this.flowEngine.registerModelLoaders({ HelloBlockModel: { // 按需加载,首次用到时才加载模块 loader: () => import('./models/HelloBlockModel'), }, }); } }

3. 用 registerFlow 添加配置项

光能渲染还不够——FlowModel 的核心价值在于可配置。通过registerFlow()可以给模型添加配置面板,让用户在界面上修改属性:

SimpleBlockModel.registerFlow({ key: 'flow1', title: tExpr('Simple Block Flow'), on: 'beforeRender', // 渲染前执行 steps: { editHtml: { title: tExpr('Edit HTML Content'), // uiSchema 定义配置面板的 UI uiSchema: { html: { type: 'string', title: tExpr('HTML Content'), 'x-decorator': 'FormItem', 'x-component': 'Input.TextArea', }, }, // 默认值 defaultParams: { html: `<h3>This is a simple block</h3> <p>You can edit the HTML content.</p>`, }, // handler 里把配置面板的值设置到 model 的 props 上 handler(ctx, params) { ctx.model.props.html = params.html; }, }, }, });

关键点解读:

  • on: 'beforeRender'— 表示这个 Flow 在渲染前执行,配置面板的值会在渲染前写入this.props
  • uiSchema— 用 JSON Schema 格式定义配置面板的 UI(语法参考 UI Schema),常用组件包括InputInput.TextAreaSelect(配合enum)、Switch等,每个字段用'x-decorator': 'FormItem'包裹即可自动带上标题和布局;
  • handler(ctx, params)params是用户在配置面板填写的值,通过ctx.model.props设置到模型上;
  • defaultParams— 配置面板的默认值。

4. 基类选择

NocoBase 提供了多个 FlowModel 基类,根据要扩展的类型选择:

基类用途详细文档
BlockModel普通区块区块扩展
DataBlockModel需要自行获取数据的区块区块扩展
CollectionBlockModel绑定数据表、自动获取数据区块扩展
TableBlockModel完整表格区块,自带字段列、操作栏等区块扩展
FieldModel字段组件字段扩展
ActionModel操作按钮操作扩展

继承链路为BlockModelDataBlockModelCollectionBlockModelTableBlockModel。通常来说,做表格区块用TableBlockModel(最常用、开箱即用),需要完全自定义渲染用CollectionBlockModelBlockModel,做字段用FieldModel,做操作按钮用ActionModel

渐进式采用:先 React 后 FlowModel

不确定的时候,先用 React 组件实现功能。等确认需要可视化配置能力后,再用 FlowModel 包装——这是推荐的渐进式做法。大块内容用 FlowModel 管理,内部细节用 React 组件实现,两者配合使用。

这一策略在实践中非常有效:FlowModel 的renderComponent()内部完全可以渲染普通 React 组件(如图表库封装),而 FlowModel 只负责对外暴露配置面板与持久化。这样既保留了配置化管理的收益,又避免了为纯内部组件引入不必要的复杂度。

相关文档索引

  • Component 组件开发 — React 组件的写法、observable/observer状态管理、useFlowContext用法;
  • FlowEngine 概述 — FlowModel 基础用法、renderComponentregisterFlowuiSchema配置与基类选择;
  • 区块扩展 —BlockModel系列基类与自定义区块注册;
  • FlowEngine 完整文档 — FlowModel、Flow、Context 的完整参考;
  • Context 上下文 —useFlowContext的完整能力介绍。

【免费下载链接】nocobaseNocoBase is an open-source AI + no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询