跳到主要内容

撤销重做

在本章节中主要介绍撤销重做插件相关的知识,通过阅读,你可以了解到

  • 如何实现元素操作的撤销与重做
  • 如何设置是否记录元素添加、删除和属性更改
  • 如何将多个改变合并为一条历史记录

使用

你可以通过插件 History 启用撤销重做功能,示例:

import { Graph, History } from '@antv/x6'

const graph = new Graph({
  background: {
    color: '#F2F7FA',
  },
})
graph.use(
  new History({
    enabled: true,
  }),
)

演示

  • 随意移动节点后,Undo 按钮变得可用。
  • 点击 Undo 按钮,节点位置被还原,然后 Redo 按钮变得可用。
  • 点击 Redo 按钮,节点位置被更新。
import './index.less'
import { createRoot } from 'react-dom/client'
import React from 'react'
import { Button } from 'antd'
import { Graph, History } from '@antv/x6'

interface Props {}

interface State {
  canUndo: boolean
  canRedo: boolean
}

export default class App extends React.Component<Props, State> {
  private container: HTMLDivElement
  private graph: Graph

  state: State = {
    canRedo: false,
    canUndo: false,
  }

  componentDidMount() {
    const graph = new Graph({
      container: this.container,
      background: {
        color: '#F2F7FA',
      },
    })

    graph.use(
      new History({
        enabled: true,
      }),
    )

    graph.addNode({
      x: 100,
      y: 60,
      width: 100,
      height: 40,
      label: 'Drag Me',
      attrs: {
        body: {
          stroke: '#8f8f8f',
          strokeWidth: 1,
          fill: '#fff',
          rx: 6,
          ry: 6,
        },
      },
    })

    graph.on('history:change', () => {
      this.setState({
        canRedo: graph.canRedo(),
        canUndo: graph.canUndo(),
      })
    })

    this.graph = graph
  }

  onUndo = () => {
    this.graph.undo()
  }

  onRedo = () => {
    this.graph.redo()
  }

  refContainer = (container: HTMLDivElement) => {
    this.container = container
  }

  render() {
    return (
      <div className="history-app">
        <div className="app-btns">
          <Button.Group>
            <Button onClick={this.onUndo} disabled={!this.state.canUndo}>
              Undo
            </Button>
            <Button onClick={this.onRedo} disabled={!this.state.canRedo}>
              Redo
            </Button>
          </Button.Group>
        </div>
        <div ref={this.refContainer} className="app-content" />
      </div>
    )
  }
}

const root = createRoot(document.getElementById('container')!)
root.render(<App />)
window.addEventListener('pagehide', () => root.unmount(), { once: true })

配置

属性名 类型 默认值 必选 描述
stackSize number 0 stackSize 为 0 表示不限制历史记录栈的长度,如果设置为其他数字表示最多只会记录该数字长度的历史记录
ignoreAdd boolean false ignoreAdd 如果为 true,添加元素不会被记录到历史记录
ignoreRemove boolean false ignoreRemove 如果为 true,删除元素不会被记录到历史记录
ignoreChange boolean false ignoreChange 如果为 true,元素属性变化不会被记录到历史记录
beforeAddCommand (event, args) => any - 当一个命令被添加到 Undo 队列前被调用,如果该方法返回 false,那么这个命令将不会被添加到 Undo 队列中
afterAddCommand (event, args, cmd) => any - 当一个命令被添加到 Undo 队列后被调用
executeCommand (cmd, revert, options) => any - 当命令被撤销或重做时被调用,revert 为 true 表示命令被撤销,否则表示命令被重做

提示

在实际项目中,我们经常会需要将多个改变一次性撤销或者重做,X6 中提供 batch 的概念,可以将多个改变合并成一个历史记录。使用方式如下:

// 方式一
graph.startBatch('custom-batch-name')
// 节点改变边框颜色以及修改位置会合并成一条记录,可以一次性撤销
node.attr('body/stroke', 'red')
node.position(30, 30)
graph.stopBatch('custom-batch-name')

// 方式二
graph.batchUpdate(() => {
  node.prop('zIndex', 10)
  node.attr('label/text', 'hello')
  node.attr('label/fill', '#ff0000')
})

API

graph.undo(…)

undo(options?: KeyValue): this

撤销。options 将被传递到事件回调中。

graph.undoAndCancel(…)

undoAndCancel(options?: KeyValue): this

撤销,并且不添加到重做队列中,因此该命令不能被重做。options 将被传递到事件回调中。

graph.redo(…)

redo(options?: KeyValue): this

重做。options 将被传递到事件回调中。

graph.canUndo()

canUndo(): boolean

是否可以撤销。

graph.canRedo()

canRedo(): boolean

是否可以重做。

graph.cleanHistory(…)

cleanHistory(options?: KeyValue): this

清空历史队列。options 将被传递到事件回调中。

graph.getHistoryStackSize(…)

getHistoryStackSize(): number

获取 history 栈的尺寸。

graph.getUndoRemainSize(…)

getUndoRemainSize(): number

获取 history undo 栈的剩余尺寸。

graph.getUndoStackSize(…)

getUndoStackSize(): number

获取 history undo 栈的尺寸。

graph.getRedoStackSize(…)

getRedoStackSize(): number

获取 history redo 栈的尺寸。

graph.isHistoryEnabled()

isHistoryEnabled(): boolean

返回是否启用了历史状态。

graph.enableHistory()

enableHistory(): this

启用历史状态。

graph.disableHistory()

disableHistory(): this

禁用历史状态。

graph.toggleHistory(…)

toggleHistory(enabled?: boolean): this

切换历史的启用状态。参数如下:

名称 类型 必选 默认值 描述
enabled boolean - 是否启用历史状态,缺省时切换历史的启用状态。

事件

事件名称 参数类型 描述
history:undo { cmds: Command[], options: KeyValue } 当命令被撤销时触发
history:redo { cmds: Command[], options: KeyValue } 当命令被重做时触发
history:cancel { cmds: Command[], options: KeyValue } 当命令被取消时触发
history:add { cmds: Command[], options: KeyValue } 当命令被添加到队列时触发
history:clean { cmds: Command[] | null, options: KeyValue } 当历史队列被清空时触发
history:change { cmds: Command[] | null, options: KeyValue } 当历史队列改变时触发
history:batch { cmds: Command, options: KeyValue } 当接收到 batch 命令时触发
graph.on('history:undo', ({ cmds }) => {
  console.log(cmds)
})

// 我们也可以在插件实例上监听事件
history.on('undo', ({ cmds }) => {
  console.log(cmds)
})
© Copyright 2026 Ant Group Co., Ltd..备案号:京ICP备15032932号-38
全站搜索
文档与示例输入关键词开始搜索

输入关键词,查找文档、API 与示例

↑↓选择↵打开Esc关闭