2013-02-18 29 views
6

我有一个相当复杂的网页,包含各种选项卡,窗体,单选按钮,下拉菜单等。它们都使用Knockout.js绑定到通过AJAX调用加载的非常复杂的JavaScript对象。当然,用户可以随心所欲地操作,在这一点上,他们点击一个按钮,将所有更改保存到服务器。是否有使用Knockout绑定页面进行跟踪的标准方式?

我正在设计一个好的设计,以跟踪页面上发生了什么变化,以便我可以实施保存。所以,我想出了一些可能的实现。

选项1)把所有东西都发回去,让服务器把它整理出来:用这个方法,我让Knockout只是更新数据源。 保存按钮会调用.toJS()并将该数据发送回服务器。 优点:这很容易,而且在客户端上只需很少的工作。 缺点:服务器并不知道发生了什么变化,必须从数据库加载数据进行比较,或者只保存所有字段。这些字段来自多个表并且具有复杂的关系。它也将整个文档视为一个单一的原子单位。如果其他人更改了字段A并且您更改了字段B,则一个用户将失去其更改。

选项2)使用JavaScript来比较原始数据和当前数据:使用这种技术,当在保存用户点击按钮,我想系统地比较原始数据和当前数据并生成图表的变化。 优点:这将理想的结果是一个精确的用户改变的图形,如果没有改变,甚至可以不操作。 缺点:我绑定的数据很复杂。它由字符串,数组,对象,对象数组,对象数组与其他对象等组成。寻找更改将是一个相当复杂的嵌套循环。

选项3)在UI中进行跟踪更改:我必须在发生更改时观察更改,并在更改UI元素时保持增量。 保存按钮只会将该更改图发送到服务器,如果它有任何挂起的更改。 优点:没有必要比较两个巨大的JavaScript对象寻求变化,但仍然有选项2. 缺点的所有优点:淘汰赛不出现有一个标准的方式使用单一听取所有的变化事件处理器。我相信我不得不诉诸绑定到所有的UI元素,或者在Knockout中创建自定义的bindingHandlers来实现这个实时更改跟踪。

我的问题:

我的问题主要是为Knockout.js专家。有没有标准的方法,或建议指导方针来解决这种明显的常见情况?发回所有的数据,甚至是没有改变的东西,一个共同的设计?或者是否有人实施自定义更改跟踪器? Knockout是否提供了任何可以减轻这种需求的框架?

更新:找到this thing,不知道它是否有用,或者如果有人对此有任何反馈。

+2

刚刚经历了一件非常相似的事情,我倾向于选择1.我们走向选择3,它以心痛结束。另一件事你必须考虑如果用户取消他们的操作(如果你允许)?你必须有一些机制来回滚更改。使用选项1,您可以向服务器请求旧数据(或者做一些更具创造性的事情,因为这看起来过多),或者您可以使用[受保护的观察值](http://www.knockmeout.net/2011/03/guard - 您的模型 - 接受 - 或 - 取消 - edits.html)。 – 2013-02-18 23:40:59

回答

1

如果它的启用/禁用保存按钮,允许用户“来自”该网页/导航状态的问题,那么你就可以用https://github.com/CodeSeven/kolite

检查检查knockout.dirtyFlag.js

希望这有助于。

编辑:请记住,您应该“永不”信任来自“用户界面”的数据。真正的比较和验证,最终会进入服务器内的“受控”环境。

1

我可能会做的是采取选择2 - 比较本身可以很简单,比如将JS对象串化并将其与其缓存版本进行比较。

讨论了其他几个选项here

P.S.也许ko.mapping可以帮助你管理这个JS对象的怪物?

1

我写了淘汰赛的变化跟踪器扩展,皮特·史密斯大大扩展...

到这里看看: https://roysvork.wordpress.com/2014/01/12/tracking-changes-to-complex-viewmodels-with-knockout-js/

它适用于延长观察到的原则,以跟踪初始状态VS 。改变用户在客户端做出的改变。我认为这个功能非常棒,并且可以向用户提供实时反馈,以了解他们修改了哪些内容。在实践中,我们实际上实现了一个保存面板,显示所有待处理的更改,甚至可以通过使用更改跟踪器的可重用功能来撤消单个更改。

ko.extenders.trackChange = function (target, track) { 
    if (track) { 
     target.isDirty = ko.observable(false); 
     target.originalValue = target(); 
     target.subscribe(function (newValue) { 
      // use != not !== so numbers will equate naturally 
      target.isDirty(newValue != target.originalValue); 
     }); 
    } 
    return target; 
}; 
相关问题