【问题标题】:Undo Redo In Angular JS在 Angular JS 中撤消重做
【发布时间】:2015-09-08 16:00:35
【问题描述】:

我在 $rootScope 中有一个大对象(比如 > 100 个对象,并且每个对象再次具有对象/数组的层次结构),我想通过 deepWatching 来 $watch 整个 $rootScope(即将 $watch 的第三个参数变为 TRUE)。

但这里的问题是,$watch 返回 2 个对象(即一个 Old RootScope 和 Modified RootScope)。然后我必须检查 $rootScope 中对象的哪些属性及其层次结构发生了变化,以将其推入堆栈。

我们是否有一种简单的方法可以在查看 $scope 时更改确切的属性?

$scope.$watch($rootScope, function(oldObj, newObj){

   //all I want here is exactly what attribute changed, NOT entire objects!

}, true);

或者,我可以在对象的每个属性上添加监视,但它似乎非常昂贵。

在 Angular js 中实现撤消/重做的最佳方法是什么?

注意 :-

  1. angular-history 不适合我的需要,因为我想查看对象的所有属性,其中可能还包含其他对象和数组。

  2. 我确信观看整个 $rootScope 也不是一个好主意,但我的目标是构建一个具有多个网格、拖放、可能包含表单、可以删除元素的 UI。所以我想构建一个整体解决方案来堆叠更改并在 CTRL + Z 上撤消它。想象一下复制桌面版 Photoshop。

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    撤消/重做基于command pattern。是的,会有很多手表;如此丰富的功能并不便宜。

    只是为了好玩,这里有一个简单(但非常有用和可扩展)的实现:http://jsfiddle.net/sYc4e/1/

    命令是知道如何应用和回滚更改的对象的接口:

    function XxxCommand() {
        // implementation specific
    }
    Command.prototype.execute = function() {
        // implementation specific
    };
    Command.prototype.rollback = function() {
        // implementation specific
    };
    

    用法:用指令装饰<input>s:

    <input name="name" undoable ng-model="data.name" />
    

    并使用带有undo-support 指令的元素(例如&lt;form&gt;)包装它们:

    <form undo-support>
    

    undoable 的链接函数监听&lt;input&gt; 的变化,并用undoableSupport 注册一个命令。 undoableSupport 的控制器跟踪命令列表。

    【讨论】:

      【解决方案2】:

      还有一个名为Angular-Chronicle 的撤消/重做库。至少对我自己来说,它是比角度历史更好的选择。

      【讨论】:

        【解决方案3】:

        库angular-history 提供撤消/重做。

        目前未维护。最近的分叉似乎是https://github.com/domoritz/angular-history。

        【讨论】:

        • 如果有人反对,请在 cmets 中提供原因。
        【解决方案4】:

        我不会查看整个 $rootScope 或任何一个包含大量项目的对象,而这些项目又包含许多需要您在每个摘要上迭代嵌套数组的项目,我会使用一个数组(使用它作为一个队列)应用到原始数据模型的更改和指向该队列中当前位置的变量。

        我会将该数组和该变量放在一个服务中,然后在发生撤消/重做时更改该索引。您可以从需要响应这些更改的任何地方查看该变量,例如指令

        【讨论】:

        • 感谢您的回复!如果我错了,请纠正我,所以你的意思是说将整个 $rootScope 保存到数组堆栈中,然后来回移动指针,这是我最初的想法,但最终浏览器会挂起,因为 $rootScope 可以是一个巨大的数据结构,可以保存为整个。推送它的多个实例可能会大大影响性能!
        • 不,不是整个 $rootScope,只是一个包含其他可能发生变化的对象的对象。
        • $rootScope.ETC 是要监视的主要对象,现在“ETC”可以包含 100 多个对象,n 每个对象可以包含其他几个对象。我需要观看整个 ETC。但是我如何准确地知道层次结构中哪个属性发生了变化?
        • 我假设您在页面上显示该对象的内容时,通过 ng-model 或指令等方式将其值与 dom 元素相关联。每当该用户更改dom 元素的值,你可以让你的指令设置一个脏标志,并以一种允许你将其与原始值相关联的方式记录更改
        • 是的,正确的。我的应用程序包含几个指令,我也可以将 $watch 放在指令级别!但问题是该指令还可以包含多个对象 n all。所以又是同样的问题,它会让我整个对象都改变了。所以最后我将最终通过对象重新诅咒以找到确切的属性更改!想象一下这个递归函数每次都被执行一次,即使是击键。当我们有 50 个指令并且每个指令至少有 50 个对象时,这将非常昂贵。
        【解决方案5】:

        我认为 LazyJsonUndoRedo 正是您想要的。

        https://github.com/azazdeaz/LazyJsonUndoRedo

        来自自述文件:

        使用 ES6 Object.observe() 或 Polymer shim 为嵌套 javascript 对象提供自动撤消/重做功能的“插入式”历史处理程序。

        http://dailyjs.com/2014/07/18/lazy-json-undo/

        【讨论】:

        • 对于在 2016 年或之后获得此答案的任何人:它不是特定于角度的,它适用于普通对象,Object.observe 是一种放弃的努力。现代的非 Angular 实现会改用 Proxy。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-12-06
        • 1970-01-01
        • 2014-10-14
        • 2018-09-09
        • 2016-02-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多