命令模式与撤销重做
vkedit 的所有元素操作(添加、删除、变换、属性更新)都通过命令对象执行。每个命令记录操作的正向和逆向逻辑,从而实现撤销重做。
命令模式原理
用户操作 -> 创建 Command -> host.executeCommand(cmd)
↓
cmd.execute() <- 执行正向操作
↓
撤销栈.push(cmd)撤销时:
host.undo() -> 撤销栈.pop() -> cmd.undo() <- 执行逆向操作
↓
重做栈.push(cmd)重做时调用 cmd.redo()(默认实现为再次调用 execute())。
内置命令
所有命令继承自 BaseCommand,构造函数第一个参数都是 host: EditorHost。
| 命令 | 构造函数 | 说明 |
|---|---|---|
AddElementCommand | (host, element) | 添加元素 |
RemoveElementCommand | (host, element) | 删除元素 |
TransformElementCommand | (host, element, oldState, newState) | 变换元素 |
UpdatePropertyCommand | (host, element, propertyPath, oldValue, newValue) | 更新属性 |
BatchCommand | (host, commands?, description?) | 批量命令 |
AlignElementsCommand | (host, alignment, elementIds) | 对齐元素 |
DistributeElementsCommand | (host, direction, elementIds) | 分布元素 |
ChangeLayerOrderCommand | (host, elementId, direction) | 改变图层顺序 |
ClearSelectionCommand | (host) | 清除选择 |
执行命令
typescript
import { AddElementCommand } from 'vkedit'
// 通过 ElementManagerPlugin 创建元素实例
const elementManager = host.getPlugin('element-manager-plugin')
const element = elementManager.createElement('rect')
element.xmm = 10
element.ymm = 10
element.wmm = 50
element.hmm = 30
// 执行命令
host.executeCommand(new AddElementCommand(host, element))撤销与重做
typescript
// 撤销上一步操作
host.undo()
// 重做被撤销的操作
host.redo()撤销/重做状态
通过监听 command:executed、command:undone、command:redone 事件感知命令栈变化。这三个事件在 host.executeCommand()、host.undo()、host.redo() 时分别触发。
批量命令
将多个操作组合为一个原子操作,撤销时按逆序回滚:
typescript
import { BatchCommand, AddElementCommand } from 'vkedit'
const commands = [
new AddElementCommand(host, rectElement),
new AddElementCommand(host, textElement),
]
// 执行批量命令(一次操作,一次撤销)
host.executeCommand(new BatchCommand(host, commands, '批量添加'))也可逐步添加:
typescript
const batch = new BatchCommand(host)
batch.addCommand(new AddElementCommand(host, rectElement))
batch.addCommand(new AddElementCommand(host, textElement))
host.executeCommand(batch)批量操作场景
拖拽创建多个元素、导入 JSON 文件时批量添加元素、一键对齐多个元素 -- 这些场景都应使用 BatchCommand。