核心架构
目的与范围
本文档说明了 relation-graph 系统的基础架构,包括其类结构、核心设计模式和组件组织方式。它概述了系统如何在保持统一核心逻辑的同时实现框架无关性。
有关特定方面的详细信息:
- 类继承细节:参见 Class Inheritance Hierarchy
- 数据结构与类型:参见 Data Model & Types
- 节点分析工具:参见 Node Analysis Utilities
- 实例生命周期:参见 Core Instance & Lifecycle
- 数据管理:参见 Data Management System
- 平台集成:参见 Platform Integration
架构概览
relation-graph 系统采用了核心-适配器架构,将与框架无关的图逻辑与特定平台的 UI 实现分离。该设计使单一代码库能够支持 Vue 2、Vue 3、React、Svelte 和 Web Components。
graph TB
subgraph "核心层(框架无关)"
CORE["RelationGraphCore
packages/relation-graph-models/models/RelationGraphCore.ts"]
DATA_PROV["RGDataProvider
packages/relation-graph-models/data/RGDataProvider.ts"]
TYPES["类型系统
packages/relation-graph-models/types.ts"]
LAYOUTS["布局引擎
packages/relation-graph-models/layouts/*"]
UTILS["工具集
packages/relation-graph-models/utils/*"]
end
subgraph "适配器层(平台特定)"
DP_VUE2["RGDataProvider4Vue2"]
DP_VUE3["RGDataProvider4Vue3"]
DP_REACT["RGDataProvider4React"]
DP_SVELTE["RGDataProvider4Svelte"]
end
subgraph "UI 层(框架组件)"
VUE2_UI["Vue 2 组件
packages/platforms/vue2/"]
VUE3_UI["Vue 3 组件
packages/platforms/vue3/"]
REACT_UI["React 组件
packages/platforms/react/"]
SVELTE_UI["Svelte 组件
packages/platforms/svelte/"]
end
CORE --> DATA_PROV
CORE --> LAYOUTS
CORE --> UTILS
CORE --> TYPES
DATA_PROV -.extends.-> DP_VUE2
DATA_PROV -.extends.-> DP_VUE3
DATA_PROV -.extends.-> DP_REACT
DATA_PROV -.extends.-> DP_SVELTE
DP_VUE2 --> VUE2_UI
DP_VUE3 --> VUE3_UI
DP_REACT --> REACT_UI
DP_SVELTE --> SVELTE_UI
VUE2_UI -.uses.-> CORE
VUE3_UI -.uses.-> CORE
REACT_UI -.uses.-> CORE
SVELTE_UI -.uses.-> CORE渐进增强继承模式
核心系统使用一种渐进增强模式,其中 RelationGraphCore 通过一条由专门化类组成的链来继承能力。每个 RelationGraphWithX 类都增加一组聚焦的能力。
graph TB
RGB["RelationGraphBase
核心工具、事件、UUID 生成
packages/.../RelationGraphBase.ts"]
RGB --> RGW1["RelationGraphWith1View
DOM 协调、坐标转换
packages/.../RelationGraphWith1View.ts"]
RGW1 --> RGW2["RelationGraphWith2Data
响应式数据集成
setReactiveData4Vue2/Vue3/React/Svelte
packages/.../RelationGraphWith2Data.ts"]
RGW2 --> RGW3O1["RelationGraphWith3Options1Update
选项管理、加载状态
_updateOptions, setCanvasOffset
packages/.../RelationGraphWith3Options1Update.ts"]
RGW3O1 --> RGW3O2["RelationGraphWith3Options2API
选项 API,创建线/节点状态
getCreatingLine, getCreatingNode
packages/.../RelationGraphWith3Options2API.ts"]
RGW3O2 --> RGW4["RelationGraphWith4Line
线路径生成
createLineDrawInfo, generateLinePath
packages/.../RelationGraphWith4Line.ts"]
RGW4 --> RGW5["RelationGraphWith5Zoom
缩放操作
zoom, setZoom
packages/.../RelationGraphWith5Zoom.ts"]
RGW5 --> RGW6E["RelationGraphWith6Effect
视觉效果、居中
zoomToFit, moveToCenter
packages/.../RelationGraphWith6Effect.ts"]
RGW6E --> RGW6L["RelationGraphWith6Layout
布局算法
doLayout, createLayout
packages/.../RelationGraphWith6Layout.ts"]
RGW6L --> RGW7["RelationGraphWith7Event
用户交互
onNodeClick, onNodeDragStart
packages/.../RelationGraphWith7Event.ts"]
RGW7 --> RGW9["RelationGraphWith9EasyView
性能模式渲染
updateEasyView, evDrawNode
packages/.../RelationGraphWith9EasyView.ts"]
RGW9 --> RGW91["RelationGraphWith91Editing
节点/线编辑
setEditingNodes, onResizeStart
packages/.../RelationGraphWith91Editing.ts"]
RGW91 --> RGW92["RelationGraphWith92MiniView
小地图概览
updateMiniView, mvDrawNode
packages/.../RelationGraphWith92MiniView.ts"]
RGW92 --> RGW93["RelationGraphWith93Image
图像生成准备
prepareForImageGeneration
packages/.../RelationGraphWith93Image.ts"]
RGW93 --> RGW95["RelationGraphWith95Dom
DOM 观察器
setDom, initDom
packages/.../RelationGraphWith95Dom.ts"]
RGW95 --> RGW99["RelationGraphWith99API
公共 API 表面
setJsonData, updateNode, getNodes
packages/.../RelationGraphWith99API.ts"]
RGW99 --> CORE["RelationGraphCore
最终实例
ready, beforeUnmount
packages/.../RelationGraphCore.ts"]
style RGB fill:#f9f9f9
style RGW2 fill:#f9f9f9
style RGW7 fill:#f9f9f9
style CORE fill:#e0e0e0能力层
| 层 | 类 | 主要职责 | 关键方法 |
|---|---|---|---|
| 基础 | RelationGraphBase |
事件系统、UUID 生成 | emitEvent(), generateNewUUID() |
| 视图 | RelationGraphWith1View |
坐标变换 | getCanvasXyByViewXy(), getViewXyByCanvasXy() |
| 数据 | RelationGraphWith2Data |
框架响应式集成 | setReactiveData4Vue2(), setReactiveData4React() |
| 选项 | RelationGraphWith3Options1Update |
配置管理 | _updateOptions(), setCheckedNode() |
| 线绘制 | RelationGraphWith4Line |
线路径计算 | createLineDrawInfo(), generateLinePath() |
| 缩放 | RelationGraphWith5Zoom |
缩放操作 | zoom(), setZoom() |
| 效果 | RelationGraphWith6Effect |
视觉效果 | zoomToFit(), moveToCenter() |
| 布局 | RelationGraphWith6Layout |
布局算法 | doLayout(), createLayout() |
| 事件 | RelationGraphWith7Event |
用户交互处理 | onNodeClick(), onNodeDragStart() |
| 性能 | RelationGraphWith9EasyView |
Canvas 渲染 | updateEasyView(), evDrawNode() |
| 编辑 | RelationGraphWith91Editing |
交互式编辑 | setEditingNodes(), onResizeStart() |
| MiniView | RelationGraphWith92MiniView |
小地图渲染 | updateMiniView(), mvDrawNode() |
| 图像 | RelationGraphWith93Image |
图像导出准备 | prepareForImageGeneration() |
| DOM | RelationGraphWith95Dom |
DOM 观察 | setDom(), initDom() |
| API | RelationGraphWith99API |
公共 API | setJsonData(), getGraphJsonData() |
| 核心 | RelationGraphCore |
实例生命周期 | ready(), beforeUnmount() |
核心组件
RelationGraphCore 实例
RelationGraphCore 是聚合所有能力的中央实例。每个 <RelationGraph /> 组件都会创建并绑定一个实例。
graph LR
subgraph "RelationGraphCore 实例"
CORE_INST["graphInstance
RelationGraphCore"]
subgraph "内部组件"
DP["dataProvider
RGDataProvider"]
OPTIONS["options
RGOptionsFull"]
LISTENERS["listeners
RGListeners"]
EVENT_HANDLERS["eventHandlers
RGEventHandler[]"]
end
subgraph "DOM 引用"
DOM["$dom
HTMLDivElement"]
CANVAS_DOM["$canvasDom
HTMLDivElement"]
end
end
CORE_INST --> DP
CORE_INST --> OPTIONS
CORE_INST --> LISTENERS
CORE_INST --> EVENT_HANDLERS
CORE_INST --> DOM
CORE_INST --> CANVAS_DOM
DP -.references.-> OPTIONS关键实例属性:
| 属性 | 类型 | 用途 |
|---|---|---|
dataProvider |
RGDataProvider |
管理图数据、节点、线 |
options |
RGOptionsFull |
配置状态 |
listeners |
RGListeners |
事件处理回调 |
eventHandlers |
RGEventHandler[] |
自定义事件处理器 |
$dom |
HTMLDivElement |
根容器元素 |
$canvasDom |
HTMLDivElement |
Canvas 容器元素 |
instanceId |
string |
唯一实例标识符 |
RGDataProvider 系统
RGDataProvider 充当图数据的单一事实来源。特定平台的数据提供器通过扩展它来集成框架的响应式系统。
graph TB
subgraph "基础数据提供器"
BASE["RGDataProvider
基础数据管理
packages/.../data/RGDataProvider.ts"]
BASE_PROPS["属性:
- graphData: RGGraphData
- options: RGOptionsFull
- commits: DataCommits
- nodeMap: Map
- linkMap: Map"]
BASE --> BASE_PROPS
end
subgraph "平台适配器"
VUE2_DP["RGDataProvider4Vue2
Vue.set() 集成
packages/.../data/RGDataProvider4Vue2.ts"]
VUE3_DP["RGDataProvider4Vue3
ref() 存储
packages/.../data/RGDataProvider4Vue3.ts"]
REACT_DP["RGDataProvider4React
setState() 钩子
packages/.../data/RGDataProvider4React.ts"]
SVELTE_DP["RGDataProvider4Svelte
Svelte stores
packages/.../data/RGDataProvider4Svelte.ts"]
end
BASE -.extends.-> VUE2_DP
BASE -.extends.-> VUE3_DP
BASE -.extends.-> REACT_DP
BASE -.extends.-> SVELTE_DP
VUE2_DP --> VUE2_UPDATE["updateViewHook()
触发 Vue 2 响应式"]
VUE3_DP --> VUE3_UPDATE["updateViewHook()
更新 ref() stores"]
REACT_DP --> REACT_UPDATE["updateViewHook()
调用 setState()"]
SVELTE_DP --> SVELTE_UPDATE["updateViewHook()
更新 Svelte stores"]数据提供器方法:
// 核心数据访问
getNodes(): RGNode[]
getLines(): RGLine[]
getLinks(): RGLink[]
getNodeById(id: string): RGNode | undefined
// 数据操作
updateNode(nodeId: string, props: Partial<RGNode>): void
updateLine(lineId: string, props: Partial<RGLine>): void
addNodes(nodes: JsonNode[]): void
addLines(lines: JsonLine[]): void
removeNode(nodeId: string): void
// 状态管理
updateOptions(options: Partial<RGOptionsFull>): void
getOptions(): RGOptionsFull
dataUpdated(): void // 触发视图更新
数据流架构
系统实现了带有响应式更新的单向数据流。
graph TB
subgraph "用户操作"
USER["用户交互
点击、拖拽、缩放"]
end
subgraph "事件层"
EVENTS["RelationGraphWith7Event
onNodeClick()
onNodeDragStart()
onLineClick()"]
end
subgraph "核心实例"
CORE["RelationGraphCore
业务逻辑"]
UPDATE_OPS["更新操作
updateNode()
updateLine()
updateOptions()"]
end
subgraph "数据提供器"
DP["RGDataProvider
数据存储"]
COMMITS["DataCommits
变更跟踪
- nodesListChanged
- linesListChanged
- changedNodes[]"]
end
subgraph "平台层"
FW_DP["平台 DataProvider
Vue2/Vue3/React/Svelte"]
STORES["响应式存储
- optionsStore
- nodesStore
- linesStore"]
end
subgraph "视图层"
COMPONENTS["UI 组件
RGCanvas
RGNodePeel
RGLinePath"]
DOM["渲染后的 DOM"]
end
USER -->|触发| EVENTS
EVENTS -->|调用方法| CORE
CORE -->|委托| UPDATE_OPS
UPDATE_OPS -->|修改| DP
DP -->|跟踪| COMMITS
DP -->|调用 updateViewHook| FW_DP
FW_DP -->|更新| STORES
STORES -.reactive binding.-> COMPONENTS
COMPONENTS -->|渲染| DOM
DOM -.user interaction.-> USER提交系统
数据提供器使用提交系统来跟踪变更,以优化更新:
interface DataCommits {
nodesListChanged: boolean; // 完整节点列表已更改
linesListChanged: boolean; // 完整线列表已更改
changedNodes: RGNode[]; // 被修改的特定节点
changedLines: RGLine[]; // 被修改的特定线
}
只有发生变更的数据才会触发响应式更新,从而避免不必要的重复渲染。
平台抽象层
该架构通过 updateViewHook 模式实现框架无关性。
graph LR
subgraph "核心逻辑(框架无关)"
CORE_METHOD["核心方法
updateNode()"]
DP_UPDATE["RGDataProvider
updateNode()"]
end
subgraph "抽象点"
HOOK["updateViewHook()
平台特定实现"]
end
subgraph "Vue 2 实现"
VUE2_IMPL["RGDataProvider4Vue2
Vue.set(node, prop, value)"]
end
subgraph "Vue 3 实现"
VUE3_IMPL["RGDataProvider4Vue3
ref.value = newValue"]
end
subgraph "React 实现"
REACT_IMPL["RGDataProvider4React
setState(newState)"]
end
subgraph "Svelte 实现"
SVELTE_IMPL["RGDataProvider4Svelte
store.set(newValue)"]
end
CORE_METHOD --> DP_UPDATE
DP_UPDATE --> HOOK
HOOK -.implements.-> VUE2_IMPL
HOOK -.implements.-> VUE3_IMPL
HOOK -.implements.-> REACT_IMPL
HOOK -.implements.-> SVELTE_IMPL平台特定初始化
每个平台初始化响应式的方式不同:
Vue 2:
// packages/relation-graph-models/models/RelationGraphWith2Data.ts:31-36
setReactiveData4Vue2(graphData, reactiveOptions, runtimeData, initRawPropertyFn)
Vue 3:
// packages/relation-graph-models/models/RelationGraphWith2Data.ts:44-60
setReactiveData4Vue3(dataStores, graphData, reactiveOptions, runtimeData, initRawPropertyFn)
React:
// packages/relation-graph-models/models/RelationGraphWith2Data.ts:68-78
setReactiveData4React(dataStores, updateViewHook)
Svelte:
// packages/relation-graph-models/models/RelationGraphWith2Data.ts:95-105
setReactiveData4Svelte(dataStores, updaters)
类型系统
类型系统为整个架构提供了强约束契约。
核心数据类型
| 类型 | 用途 | 位置 |
|---|---|---|
RGNode |
带布局数据的运行时节点 | packages/relation-graph-models/types.ts:245-275 |
JsonNode |
可序列化节点 | packages/relation-graph-models/types.ts:206-241 |
RGLine |
运行时线 | packages/relation-graph-models/types.ts:355-358 |
JsonLine |
可序列化线 | packages/relation-graph-models/types.ts:295-339 |
RGLink |
带节点引用的线 | packages/relation-graph-models/types.ts:371-380 |
RGOptions |
用户配置 | packages/relation-graph-models/types.ts:688 |
RGOptionsFull |
完整配置 | packages/relation-graph-models/types.ts:641-684 |
RelationGraphInstance |
核心实例类型 | packages/relation-graph-models/types.ts:30 |
类型关系
graph TB
JSON_NODE["JsonNode
用户输入格式
可序列化"]
RG_NODE["RGNode
运行时格式
+ lot (layout)
+ rgShouldRender
+ rgCalcedVisibility"]
JSON_LINE["JsonLine
用户输入格式
from: string
to: string"]
RG_LINE["RGLine
运行时格式
+ id
+ isReverse"]
RG_LINK["RGLink
链接对象
+ fromNode: RGNode
+ toNode: RGNode
+ line: RGLine"]
JSON_NODE -->|json2Node| RG_NODE
RG_NODE -->|transNodeToJson| JSON_NODE
JSON_LINE -->|json2Line| RG_LINE
RG_LINE --> RG_LINK
RG_NODE --> RG_LINK事件系统
事件系统通过分层事件发射模型提供可扩展性。
graph TB
subgraph "事件源"
USER_ACTION["用户操作
例如,节点点击"]
INTERNAL["内部事件
例如,布局完成"]
end
subgraph "事件发射(RelationGraphBase)"
EMIT["emitEvent(eventName, ...args)"]
DEFAULT["defaultEventHandler()
检查 listeners 属性"]
CUSTOM["自定义事件处理器
eventHandlers: RGEventHandler[]"]
HOOK["_emitHook
Vue emit 集成"]
end
subgraph "事件处理器"
LISTENER["RGListeners
onNodeClick
onNodeDragStart
onLineClick
等等"]
HANDLER["自定义处理器
addEventHandler(handler)"]
end
USER_ACTION --> EMIT
INTERNAL --> EMIT
EMIT --> DEFAULT
EMIT --> CUSTOM
EMIT --> HOOK
DEFAULT --> LISTENER
CUSTOM --> HANDLER事件类型
// packages/relation-graph-models/types.ts
enum RGEventNames {
onReady = "onReady",
onNodeClick = "onNodeClick",
onNodeDragStart = "onNodeDragStart",
onNodeDragging = "onNodeDragging",
onNodeDragEnd = "onNodeDragEnd",
onLineClick = "onLineClick",
onCanvasClick = "onCanvasClick",
onNodeExpand = "onNodeExpand",
onNodeCollapse = "onNodeCollapse",
onZoomEnd = "onZoomEnd",
// ... 更多
}
事件发射流程:
- 用户操作触发事件处理方法(例如
onNodeClick()) - 方法调用
emitEvent(RGEventNames.onNodeClick, node, e) - 系统检查
defaultEventHandler()中已注册的监听器 - 调用
eventHandlers数组中的自定义事件处理器 - 调用
_emitHook以进行框架集成(Vue emit) - 如果提供了自定义结果则返回该结果,从而允许取消事件
关键设计模式
1. 通过继承实现渐进增强
每个 WithX 类增加一个关注点,从而形成清晰的职责分离。此模式:
- 使代码库可测试(每一层可独立测试)
- 支持部分功能采用
- 明确依赖链
2. 核心-适配器模式
框架无关核心 + 平台特定适配器:
RelationGraphCore不包含框架代码- 平台适配器(
RGDataProvider4Vue2等)处理响应式 - UI 组件消费核心实例
3. 数据提供器作为单一事实来源
所有数据修改都通过 RGDataProvider:
- 集中式状态管理
- 通过 commits 进行变更跟踪
- 跨平台一致的 API
4. 用于 DOM 集成的观察者模式
RelationGraphWith95Dom 使用浏览器观察器:
ResizeObserver用于元素尺寸变化MutationObserver用于 DOM 变更- 将 DOM 监控与业务逻辑解耦
5. 用于布局的工厂模式
createLayout() 实例化布局算法:
RGTreeLayout、RGForceLayout、RGCircleLayout等- 可插拔布局系统
- 配置驱动的选择
该架构使 relation-graph 能够在支持多个框架的同时维护单一代码库,从而同时实现代码复用和平台原生的响应式模式。渐进增强模式使功能扩展时的复杂度保持可控,而核心-适配器模式则确保图逻辑与 UI 集成之间的清晰分离。