【问题标题】:Is there a standard way of change tracking with a Knockout bound page?是否有使用 Knockout 绑定页面进行更改跟踪的标准方法?
【发布时间】:2013-02-03 11:16:51
【问题描述】:

我有一个相当复杂的网页,其中包含各种选项卡、表单、单选按钮、下拉菜单等。所有这些都使用 Knockout.js 绑定到通过 AJAX 调用加载的非常复杂的 JavaScript 对象。当然,用户可以随心所欲地处理内容,此时他们点击保存按钮将所有更改保存回服务器。

我正在想出一个好的设计来准确跟踪页面上的更改,以便我可以实现保存。所以,我想出了一些可能的实现。

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

选项2)使用JavaScript比较原始数据和当前数据:使用这种技术,当用户点击保存按钮时,我会系统地比较原始数据和当前数据并生成变化图。 优点: 理想情况下,这将产生一个关于用户更改内容的紧凑图表,如果没有任何更改,甚至可以无操作。 缺点:我绑定的数据很复杂。它由字符串、数组、对象、对象数组、对象数组与其他对象等组成。查找更改将是一个相当复杂的嵌套循环。

选项 3) 跟踪 UI 中的更改: 我必须在更改发生时观察更改,并在 UI 元素更改时保持增量。 Save 按钮只会将该更改图发送到服务器,如果它有任何待处理的更改。 优点: 无需比较两个巨大的 JavaScript 对象来寻找变化,但仍然具有选项 2 的所有优点。缺点: 不会出现淘汰赛 em> 有一个标准的方法来使用单个事件处理程序来监听所有更改。我相信我将不得不求助于绑定到所有 UI 元素,或者在 Knockout 中创建自定义 bindingHandlers 来实现这种实时更改跟踪。

我的问题:

我的问题主要是针对 Knockout.js 专家的。是否有解决这种明显常见情况的标准方法或推荐指南?发回所有数据,甚至是未更改的数据,是一种通用设计吗?还是人们正在实施自定义变更跟踪器? Knockout 是否提供任何类型的框架来简化此要求?

更新:找到this thing,不确定它是否有用或是否有人对此有任何反馈。

【问题讨论】:

  • 刚刚经历了非常相似的事情,我倾向于选项 1。我们转向选项 3,结果以心痛告终。你必须考虑的另一件事是如果用户取消他们的操作(如果你允许的话)怎么办?您必须有一些机制来回滚更改。使用选项 1,您可以向服务器询问旧数据(或者做一些更有创意的事情,因为这似乎太过分了),或者您可以使用 protected observable

标签: javascript ajax json knockout.js


【解决方案1】:

如果是启用/禁用“保存”按钮的问题,允许用户“从”该页面/状态导航,那么您可以通过 https://github.com/CodeSeven/kolite 进行检查

检查 knockout.dirtyFlag.js

希望这会有所帮助。

编辑:请记住,您应该“从不”相信来自“UI”的数据。真正的比较和验证最终会在服务器内的“受控”环境中进行。

【讨论】:

    【解决方案2】:

    我可能会选择选项 2 - 比较本身可以像字符串化 JS 对象并将其与自身的缓存版本进行比较一样简单。

    讨论了其他一些选项here

    附:或许ko.mapping可以帮你管理这个JS对象的怪物?

    【讨论】:

      【解决方案3】:

      我为淘汰赛编写了一个更改跟踪器扩展,Pete Smith 大大扩展了它......

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

      它的工作原理是扩展 observable 以跟踪初始状态与用户在客户端上所做的更改。我认为这非常有效,可以为用户提供实时反馈以了解他们修改了什么。在实践中,我们实际上实现了一个保存面板,它显示所有待处理的更改,甚至可以让它们撤消单个更改,所有这些都是通过使用更改跟踪器的可重用功能来实现的。

      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;
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-24
        • 2011-10-16
        • 1970-01-01
        • 2012-05-03
        相关资源
        最近更新 更多