2012-11-18 18 views
1

我使用Stripe併爲了避免任何PCI遵從問題,我的表單上輸入的信用卡數據不應該從瀏覽器傳輸到服務器。用戶應使用Knockout.js將信用卡數據輸入到表單中。防止對象被Knockout.js序列化爲JS/toJSON

大部分爲了感興趣的問題(主要是我更好地理解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函數(即避免緩存它)?

我只是好奇如何用Knockout.js去做這種事情。

回答

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

然後,它只是增加了可觀察到您的視圖模型的問題和你設置。

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."); 
    }); 
} 

當然,這依賴於無證行爲。淘汰賽決定這些事情的方式在未來可能會改變。使用風險自負。

+0

感謝傑夫顯示:與Object.create()創建對象時

例如。這當然是這個想法,並且這適用於排除密碼屬性的簡單情況。這不是我正在尋找的,因爲1)我想要一些可以放入可重用模型的通用庫的東西,2)這隻能省略一個觀測值,我想要一個明確的錯誤(而不是無聲的省略)整個ViewModel拒絕序列化,3)我認爲這不適用於'ko {mapping} .toJS/toJSON'。儘管感謝您爲討論做出貢獻! –

+0

哦,所以你想要這個錯誤,即使在'toJS'函數。我認爲這是可行的,但不確定是否可行。 –

2

只是一個替代我發現車禍後第一次閱讀這篇文章:

如果設置enumerable選項物業的false它不會被序列化。

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

在這種情況下items不會序列化的字符串從ko.toJSON()

+0

感謝@大衛 - 好。另一個可行的方法是使用「Symbol」作爲屬性名稱(因爲它們是默認情況下不可枚舉的)。 –