使用Knockout.js toJS / toJSON阻止对象序列化

时间:2012-11-18 02:00:25

标签: knockout.js

我正在使用Stripe并且为了避免任何PCI合规性问题,我的表单上输入的信用卡数据永远不会从浏览器传输到服务器。用户应使用Knockout.js将信用卡数据输入表格。

主要是为了感兴趣(主要是因为我更了解knockout.js是如何工作的),我想提出一种方法,通过在数据序列化时出现明显错误来防止信用卡数据的序列化以通常的knockout.js方式尝试(即ko.toJSko.toJSONko.mapping.*等价物。

为了达到这个目的,我认为我可以做一些聪明的事情,就像这样(在CoffeeScript中):

class NeverSerialize
  datums = ko.observable()
  blocker = ko.computed(
    read: () -> throw new Error("You shall not pass!")
    deferEvaluation: true
  )

当调用ko.toJS/toJSON或等效时,它将执行blocker(),这将调用read函数并成为它的结尾。

这个想法几乎可行 - 正如您从this jsFiddle所看到的那样。不幸的是,它只是第一次执行read(),但它永远不会被调用。我收集这是因为没有read所依赖的可观察量,所以淘汰假设计算的值不会改变。

所以我想我对两件事感到好奇:

  1. 这在概念上是一种明智的方法来防止使用ko.toJS/toJSON序列化观察者吗? (或者,通常,只要在计算的可观察量上调用read就执行函数)

  2. 如何在每次访问时调用计算变量的read函数(即避免缓存它)?

  3. 我很好奇人们如何使用Knockout.js来解决这类问题。

3 个答案:

答案 0 :(得分:2)

而不是完成所有这些,只需定义一个toJSON函数,它将返回一个包含要序列化的属性的对象。即,创建视图模型的副本,并从不希望序列化的副本中删除属性。

function ViewModel(model) {
    this.name = ko.observable(model.name);
    this.password = ko.observable(model.password);

    this.toJSON = function () {
        var copy = ko.toJS(this);
        delete copy.password;
        return copy;
    }
}

如果你真的想这样做,我想你可以做到这一点。 ko.toJS函数遍历对象的所有属性,并将值映射到新对象。因此,如果它不是可观察的,它将简单地复制它,否则它将调用(读取)它。你需要欺骗淘汰无条件地调用你的observable,所以你可能总是在阅读时抛出错误。

您可以编写一个新的可观察层次结构,它将是一个非缓存版本,但这可能是您可能不需要的很多东西。您只需要创建一个最终会抛出错误的observable。所以你可以做的就是创建一个函数,它只会抛出一个错误并且会让人觉得它是一个可观察的东西。幸运的是,淘汰赛通过特殊财产看到它有一个可观察的原型来检查这一点。

ko.errorObservable = function (thrower) {
    function errorObservable() {
        if (typeof thrower === 'function') {
            thrower();
        }
    }
    // trick knockout into thinking this is an observable so it will be invoked
    errorObservable[ko.observable.protoProperty] = ko.observable;
    return errorObservable;
};

然后,只需将observable添加到视图模型中即可设置。

function ViewModel(model) {
    this.name = ko.observable(model.name);
    this.password = ko.observable(model.password);
    this._neverSerialize = ko.errorObservable(function () {
        throw new Error("Serialization of this model is prohibited.");
    });
}

当然,这依赖于无证件的行为。淘汰的方式决定了这些事情将来可能会发生变化。使用风险自负。

答案 1 :(得分:2)

在我第一次阅读这篇文章后,我偶然发现了另一种选择:

如果您将该属性的enumerable选项设置为false,则不会将其序列化。

例如,使用Object.create()创建对象时:

const obj = Object.create(objProto, {
        name: { value: name, enumerable: true },
        items: { value: items, enumerable: false }
    });

在这种情况下items将不会显示在ko.toJSON()的序列化字符串中

答案 2 :(得分:1)

这是关于knockmeout

的文章

这与杰夫的答案基本相同,但只有更多细节。

http://www.knockmeout.net/2011/04/controlling-how-object-is-converted-to.html