Handsonetable - undo/redo 多个组件实例

Handsonetable - undo/redo over multiple instances of component

我正在考虑在我的项目中使用 Handsontable (https://github.com/handsontable/handsontable)。

我需要在页面上有多个 table 组件,

并且有两个自己的 undo/redo 按钮,用于处理 undo/redo 对所有组件的操作,顺序与用户所做的更改相同。

我的意思是用户在 table A 中进行了更改,然后在 table B 中进行了更改,然后又在 table A 中进行了更改。然后,如果他点击撤消,那么 A 将被更改,之后下一个命中 B 被更改,然后下一个命中 A 被改回。

有没有可能做到这一点?

这样我们就可以结束这个问题,并且对于那些想要获得有关如何执行此操作的建议的人,这里有一个关于如何实现此功能的简短想法:

假设:

  • 我们有 Handsontable 的实例,它有 undoredo 方法,根据 Handsontable 文档定义如下。
  • 我们有两个按钮 ids #undo#redo 来触发 行为。

方法:

undo (): 撤销上次编辑

redo (): 重做编辑(用于撤销撤销)


逻辑

技巧很简单。我们将使用两个全局数组,抽象 Queues,定义为 undoQredoQ,它们将跟踪要修改的最后一个 HOT 实例的引用。每次在任何 HOT 实例上触发 afterChange 事件、按下 redo 按钮以及按下 undo 按钮时,这些 Queue 都会被修改。为了避免这种方法过于复杂,我们不会针对 space 进行优化,但我会记下它,以便如果您需要它,您可以尝试自己做。

免责声明:您没有提到当一个或另一个 table 处于焦点时会发生什么。 HOT 的工作方式是 ctrl-z,如果启用,将 undo 以 table 为焦点。如果你愿意,你可以禁用它。

详细实施

第 1 步: 添加事件逻辑

按如下方式添加afterChange事件挂钩,如果您已有自定义事件,则追加逻辑;这在 HOT 实例的 options 的声明中。

afterChange: function() {
    return function(changes, source) {
        var hotInstance = this;
        // check that the `undo` event was initialized before pushing
        if (hotInstance.undo) {
            undoQ.push(this);
            redoQ = []; // IMPORTANT: this clears the redo array as do most undo operations, but you can add different logic if you'd like
        }
        // other logic if you have some
    }
}

这将在发生更改时将 RE​​FERENCE 推送到每个 table。请注意,这个数组可能会变大,但不会太大。原因是 afterChange 事件每 change 只触发一次。但是,这是可以进行优化的地方。相反,如果您注意到触发此事件的次数多得离谱,您可以做的是检查队列中的最后一个元素是否与 this 相同,如果是,则增加一个计数器,而不仅仅是附加参考。然后在 undoredo 上,减少计数器直到它们达到零,然后弹出。

步骤 2: 添加撤消和重做逻辑

这一步比较直观。您要做的是将以下逻辑添加到 undoredo 按钮点击的回调中。

$("#undo").on("click", function() {
    if (undoQ.length > 0) {
        var hotInstance = undoQ.shift();
        hotInstance.undo();
        redoQ.push(hotInstance);
    }
})

$("#redo").on("click", function() {
    if (redoQ.length > 0) {
        var hotInstance = redoQ.shift();
        hotInstance.redo();
        undoQ.push(hotInstance);
    }
})

我们在这里所做的是手动触发最后更改的 table 的相应事件。请记住,更改后,redoQ 会被清空,但只要没有,您应该可以毫无问题地撤消和重做。

应该是这样。祝你好运!