【问题标题】:How do I copy a javascript object into a temporary variable that I can use to restore my original object after I've changed it's properties?如何将 javascript 对象复制到临时变量中,以便在更改属性后恢复原始对象?
【发布时间】:2017-02-25 00:05:51
【问题描述】:

很难想出一个描述性的标题,但我想要实现的是:

  • 我有一个 Knockout Observable 绑定到表格行。
  • 我有一个编辑按钮,它向用户显示了许多输入字段,这些字段也绑定到同一个可观察对象,允许用户编辑表格行中的内联值。
  • 我想在用户单击“编辑”按钮时将我的 observable 保存在一个临时变量中,以便在用户想放弃他们的编辑时撤消更改。

如何使用 javascript 以简洁的方式实现这一点?我的对象除了普通属性之外还有方法。


这些是我已经知道的黑客:

  • 将我的对象转换为 JSON 格式并返回。 (不适用于方法)
  • 不同种类的“克隆”方法。 (没有找到适合我的)
  • 从服务器重新加载数据并重新映射 observable。

【问题讨论】:

  • 您可以将其作为 JSON 存储在本地存储中。检查here。您可以像这样转换为 JSON 'var json = ko.toJSON(observable);'
  • @Rex 是的,但这不会保留我的对象上的方法,我将不得不重新映射 observable。理想情况下,我正在寻找一个仅限 javascript 的解决方案。
  • 如果data 是引用类型,您的 C# 代码也将无法工作......奇怪的是,您以某种方式发现该技巧不适用于 Javascript,然后认为在 C# 中它的工作方式不同?
  • @MarioDS 你当然是对的,我不确定是什么让我这么认为。谢谢。

标签: javascript knockout.js


【解决方案1】:

您可以使用 extender 来存储您的 observable 以前的值:

ko.extenders.keepHistory = function(target, option) {
    target.subscribe(function(newValue) {
       if(!target.history) target.history = ko.observableArray();
       target.history.push(newValue);
    });
    return target;
};

用法:

var vm = function () {
    var self = this;
    this.someValue = ko.observable().extend({keepHistory: true});
}

看到这个(更新)demo

更新

好的,我已经进行了更改以在扩展程序中实现 revert

ko.extenders.keepHistory = function(target, option) {
    target.subscribe(function(newValue) {
       if (target.reverting) { target.reverting = false; return; }
       if(!target.history) target.history = ko.observableArray();
       if(!target.revert) {
           target.revert = function () {
           console.log(target.history()[target.history().length -3]);
                var previousVersion = target.history().length < 2 ? null : target.history()[target.history().length -2];
              if (!!previousVersion) {
                  target.reverting = true;
                  console.log(previousVersion);
                  target(previousVersion);
              }
           }
       }
       target.history.push(newValue);
       console.log(target.history());
    });
    return target;
};

查看最新的demo。 请注意,我使用了 ES6 clone 方法(参见 this post)。

【讨论】:

  • 好主意,我怎样才能实现撤消功能并保持扩展器自包含?
【解决方案2】:

我对这类功能的首选方法通常是:

  • 拥有一个您希望能够编辑的对象的视图模型
  • 定义一个自己的export 函数,输出视图模型实例独有的数据
  • 定义一个import 函数,可以将这些数据映射回它们的属性

示例

例如,假设您有一个Person 视图模型。虽然视图模型可以包含方法和计算属性,但用户可以编辑两个字段:firstNamelastName:我们将在开始编辑时将它们导出到普通对象。

import 上,我们使用这个对象来设置我们的可观察值,自动重新计算我们的displayName 属性和状态计算。

如果您希望它更通用,您可以将这些方法包含在它们自己的类中,并使用组合将功能添加到其他视图模型。

var Person = function(firstName, lastName) {
  this.firstName = ko.observable(firstName);
  this.lastName = ko.observable(lastName);
  
  this.displayName = ko.pureComputed(function() {
    return [this.firstName(), this.lastName()].join(" ");
  }, this);
  
  this.saved = ko.observable(null);
  
  this.isEditing = ko.pureComputed(function() {
    return this.saved() !== null;
  }, this);
};

Person.prototype.export = function() {
  return {
    firstName: this.firstName(),
    lastName: this.lastName()
  }
};

Person.prototype.import = function(obj) {
  this.firstName(obj.firstName);
  this.lastName(obj.lastName);
}

Person.prototype.startEdit = function() {
  this.saved(this.export());
};

Person.prototype.cancelEdit = function() {
  this.import(this.saved());
  this.saved(null);
};

Person.prototype.saveEdit = function() {
  this.saved(null);
};

var App = function() {
  this.people = ko.observableArray([
    new Person("Jane", "Doe"),
    new Person("John", "Doe")
  ]);
};

ko.applyBindings(new App());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<ul data-bind="foreach: people">
  <li>
    
    <!-- ko ifnot: isEditing -->
    <p data-bind="text: displayName"></p>
    <button data-bind="click: startEdit">edit</button>
    <!-- /ko -->
    
    <!-- ko if: isEditing -->
    <p>
      <input data-bind="textInput: firstName" type="text">
      <input data-bind="textInput: lastName" type="text">
    </p>
    <button data-bind="click: cancelEdit">cancel</button>
    <button data-bind="click: saveEdit">save</button>
    <!-- /ko -->
    
  </li>
</ul>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-09
    • 2016-12-01
    • 2021-05-15
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-04
    相关资源
    最近更新 更多