历史记录与撤销重做 (HistoryPlugin)
createHistoryPlugin 基于纯快照栈实现完整的操作历史管理,支持 Ctrl+Z 撤销 / Ctrl+Y 重做 键盘快捷键,以及跳转到任意历史步骤的时间旅行功能。
快速上手
typescript
import { createHistoryPlugin } from '@yh-ui/flow'
onMounted(() => {
// 1. 创建并安装插件
const plugin = createHistoryPlugin({
maxHistory: 100, // 最多保存 100 步历史
enableKeyboard: true, // 启用 Ctrl+Z / Ctrl+Y 快捷键
onHistoryChange: (canUndo, canRedo, length) => {
// 根据状态更新 UI(按钮禁/启用)
}
})
flowRef.value?.usePlugin(plugin)
// 2. 插件安装后,在关键操作时机手动保存快照
// (推荐:精确控制历史粒度,性能最优)
})
// 3. 在合适的时机调用(拖拽结束 / 连线创建 / 删除等)
const handleDragEnd = () => flowRef.value?.saveSnapshot?.('拖动节点')
// 4. 撤销/重做(也可以直接按 Ctrl+Z / Ctrl+Y)
const undo = () => flowRef.value?.undo?.()
const redo = () => flowRef.value?.redo?.()IMPORTANT
saveSnapshot、undo、redo 等方法是在 usePlugin 安装插件后 动态挂载到 flowRef.value 上的。 因此必须在 onMounted 后才能调用这些方法(组件 ref 及插件均已就绪)。
基础用法演示
撤销/重做 — 保存快照后可撤销/重做节点位置
API
HistoryPluginOptions
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled | boolean | true | 是否启用插件 |
maxHistory | number | 100 | 最大历史记录步数(超出则自动丢弃最旧步骤) |
enableKeyboard | boolean | true | 是否注册 Ctrl+Z/Y 键盘快捷键(全局 window 级) |
onHistoryChange | (canUndo, canRedo, length) => void | — | 历史变化时的回调,用于更新按钮状态 |
插件安装后的 FlowInstance 扩展方法
通过
flowRef.value?.usePlugin(plugin)安装后,以下方法/属性自动挂载到flowRef.value
| 方法/属性 | 类型 | 说明 |
|---|---|---|
undo() | () => void | 撤销到上一快照 |
redo() | () => void | 重做到下一快照 |
saveSnapshot(desc?) | (description?: string) => void | 手动保存当前 nodes + edges 快照 |
clearHistory() | () => void | 清空所有历史记录 |
jumpToStep(index) | (index: number) => void | 跳转到指定历史步骤(时间旅行) |
getHistory() | () => FlowHistorySnapshot[] | 获取完整历史列表 |
canUndo | Ref<boolean> | 是否可撤销(响应式) |
canRedo | Ref<boolean> | 是否可重做(响应式) |
historyLength | Ref<number> | 当前历史条数(响应式) |
FlowHistorySnapshot 类型
typescript
interface FlowHistorySnapshot {
nodes: Node[]
edges: Edge[]
timestamp: number
description?: string
}键盘快捷键
| 快捷键 | 说明 |
|---|---|
Ctrl + Z / ⌘ + Z | 撤销 |
Ctrl + Y / ⌘ + Y | 重做 |
Ctrl + Shift + Z / ⌘ + ⇧ + Z | 重做(macOS 兼容) |
最佳实践
TIP
不推荐开启 autoCapture(自动捕获所有变化),建议在业务操作的关键时机手动调用 saveSnapshot:
typescript
// ✅ 推荐:在关键时机手动保存,精确控制历史粒度
flowRef.value?.on('node:dragend', () => flowRef.value?.saveSnapshot?.('拖动节点'))
// 连线创建后保存
// 删除操作前保存
// 用户手动点击"保存"按钮时保存