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 的实例,它有
undo
和 redo
方法,根据 Handsontable 文档定义如下。
- 我们有两个按钮
id
s #undo
和 #redo
来触发
行为。
方法:
undo (): 撤销上次编辑
redo (): 重做编辑(用于撤销撤销)
逻辑
技巧很简单。我们将使用两个全局数组,抽象 Queue
s,定义为 undoQ
和 redoQ
,它们将跟踪要修改的最后一个 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
}
}
这将在发生更改时将 REFERENCE 推送到每个 table。请注意,这个数组可能会变大,但不会太大。原因是 afterChange
事件每 change
只触发一次。但是,这是可以进行优化的地方。相反,如果您注意到触发此事件的次数多得离谱,您可以做的是检查队列中的最后一个元素是否与 this
相同,如果是,则增加一个计数器,而不仅仅是附加参考。然后在 undo
或 redo
上,减少计数器直到它们达到零,然后弹出。
步骤 2: 添加撤消和重做逻辑
这一步比较直观。您要做的是将以下逻辑添加到 undo
和 redo
按钮点击的回调中。
$("#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
会被清空,但只要没有,您应该可以毫无问题地撤消和重做。
应该是这样。祝你好运!
我正在考虑在我的项目中使用 Handsontable (https://github.com/handsontable/handsontable)。
我需要在页面上有多个 table 组件,
并且有两个自己的 undo/redo 按钮,用于处理 undo/redo 对所有组件的操作,顺序与用户所做的更改相同。
我的意思是用户在 table A 中进行了更改,然后在 table B 中进行了更改,然后又在 table A 中进行了更改。然后,如果他点击撤消,那么 A 将被更改,之后下一个命中 B 被更改,然后下一个命中 A 被改回。
有没有可能做到这一点?
这样我们就可以结束这个问题,并且对于那些想要获得有关如何执行此操作的建议的人,这里有一个关于如何实现此功能的简短想法:
假设:
- 我们有 Handsontable 的实例,它有
undo
和redo
方法,根据 Handsontable 文档定义如下。 - 我们有两个按钮
id
s#undo
和#redo
来触发 行为。
方法:
undo (): 撤销上次编辑
redo (): 重做编辑(用于撤销撤销)
逻辑
技巧很简单。我们将使用两个全局数组,抽象 Queue
s,定义为 undoQ
和 redoQ
,它们将跟踪要修改的最后一个 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
}
}
这将在发生更改时将 REFERENCE 推送到每个 table。请注意,这个数组可能会变大,但不会太大。原因是 afterChange
事件每 change
只触发一次。但是,这是可以进行优化的地方。相反,如果您注意到触发此事件的次数多得离谱,您可以做的是检查队列中的最后一个元素是否与 this
相同,如果是,则增加一个计数器,而不仅仅是附加参考。然后在 undo
或 redo
上,减少计数器直到它们达到零,然后弹出。
步骤 2: 添加撤消和重做逻辑
这一步比较直观。您要做的是将以下逻辑添加到 undo
和 redo
按钮点击的回调中。
$("#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
会被清空,但只要没有,您应该可以毫无问题地撤消和重做。
应该是这样。祝你好运!