1

我正在使用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函数并结束它。

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

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

  1. 从概念上讲,这是否是防止可观察对象被序列化的明智方法ko.toJS/toJSON?(或者,一般来说,只要read在计算的 observable 上调用 a ,就执行一个函数)

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

我只是好奇如何使用 Knockout.js 来处理这种事情。

4

3 回答 3

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,因此您可能总是在读取它时抛出错误。

你可以编写一个新的可观察层次结构,它是一个非缓存版本,但这是你可能不需要的很多东西。你只需要创建一个最终抛出错误的可观察对象。所以你可以做的是创建一个函数,它只会抛出一个错误并欺骗淘汰赛认为它是一个可观察的。幸运的是,knockout 通过一个特殊的属性看到它有一个作为原型的 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.");
    });
}

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

于 2012-11-18T05:56:55.827 回答
2

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

如果enumerable将属性的选项设置为false它将不会被序列化。

例如,当创建一个对象时Object.create()

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

在这种情况下items,不会出现在序列化字符串中ko.toJSON()

于 2015-10-02T15:28:26.323 回答
1

这是一篇关于knockmeout

它与 Jeff 的答案基本相同,但有更多细节。

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

于 2014-06-19T05:20:03.560 回答