2015-08-29 149 views
0

我遇到了一些使用Knockout進行數據綁定的表單設計的架構問題。爲了簡單起見,我有一個相當龐大的項目,讓我們說我打了一個API端點(但不是RESTful),並獲得了一個JSON響應。我目前通過自定義映射函數運行此響應,以將所有屬性變爲觀察值。表單工作正常,但我現在想要使用Knockout驗證來添加驗證。我們還沒有構建所有不同的規則,但我想深入瞭解的答案是通過我的可觀察地圖添加規則的最佳方法。另外令人頭疼的是,返回的響應具有的屬性因服務器上可以在UI中更新的某些設置而異,所以我不會爲我可能需要的任何準備工作做好準備。我知道這是非常混亂,所以也許是模糊的,人爲的例子將幫助:使用Knockout驗證的表單驗證

前提條件:

results: [ 
    { a: 1 }, 
    { b: 2 }, 
    { c: 3 } 
] 

處理:

var arr = ko.observableArray([]); 

$.get('/endpoint/').then(function(data) { 
    data.results.forEach(function(result) { 
    arr.push(mapToObservables(result)); 
    }); 
}); 
設置X是在頁面加載

JSON響應啓動

設置Y已啓用,屬性「c」不再相關,但「d」是,因此需要返回的JSON是:

updates: [ 
    { a: 1 }, 
    { b: 3 },(updated value) 
    { d: 4 } (new value) 
] 

我最初觀察屬性「a,b,c」,所以「a,b」很好,因爲它們的狀態仍然是已知的。但是由於設置改變,需要添加屬性「d」,並且我還沒有注意到它。

這個例子很有人氣,但我不想有任何知識產權問題,所以希望它是有道理的。真正的應用程序要大得多,並且對同一端點的不同GET/POST可能導致6或7種不同的狀態。它看起來沒有很大的可擴展性/可維護性來檢查「是X集合嗎?然後用適當的規則將Y和Z的屬性設置爲空觀察值,以防萬一」(並且對於其他可能的場景也是如此)。

我真的希望這對於能指導我的人來說甚至有點意義。我進入這個項目時甚至不知道Knockout是什麼或者以前的應用程序如何工作,所以嘗試吸收所有相關知識時有點瘋狂。感謝您提前一切!

編輯:

我已經接受了羅伊的回答以下,因爲它是最接近於我正在尋找,但一點更清晰,想象這個場景。我打了一個端點,可以發回屬性a,b,cd(但總是一個子集,從來不是全套)。如果我回到ab,我可以很容易地使用ko.mapping使它們可以觀察到,以防它們發生變化。但是,我需要做的是允許用戶基本上擺脫b,並選擇c來代替。如果用戶想要使用它們,我想不出在頁面加載時爲「c」和「d」「設置」可觀察對象的乾淨方式,以便它們可以使用。唯一想到的是,我爲我的應用程序中的所有可能字段設置了可觀察值,即使90%的時間,其中一半不會被使用。或者我想我可以使用像郵箱這樣的pubsub系統在運行時動態創建需要的可觀察對象。我知道使用observables存在一些開銷,但是對於我來說它們看起來相當輕量級,所以我不確定在考慮開發的性能和時間時哪種方法是「最好的」。

+0

我不知道,但我認爲你想看看'ko.mapping.fromJS',這將創建一個從JS對象成員可觀。 –

+0

感謝您的答案,不幸的是,它並沒有真正解決這個問題。我沒有用映射插件獲得最好的運氣,所以我編寫了自己的方法來映射來自JSON響應的觀察值,但是考慮到最初可能無法從服務器返回的屬性是我的困難所在。我現在就把問題留給開放,但我很欣賞這種迴應。 –

+0

我會創建所有的屬性作爲observables,並且還爲每個屬性創建一個標誌(observable)來表示它是否被使用。 –

回答

1

這是你要找的行爲嗎?

var d1 = { 
 
    a: 1, 
 
    b: 2 
 
}; 
 
var d2 = { 
 
    a: 'oo', 
 
    c: 'ah' 
 
}; 
 

 
var vm = { 
 
    data:ko.observable() 
 
    }; 
 
vm.data(ko.mapping.fromJS(d1)); 
 
setTimeout(function() { 
 
    vm.data(ko.mapping.fromJS(d2)); 
 
}, 1000); 
 

 

 
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script> 
 
<div data-bind="if:data().a">A:<span data-bind="text:data().a"></span> 
 
</div> 
 
<div data-bind="if:data().b">B:<span data-bind="text:data().b"></span> 
 
</div> 
 
<div data-bind="if:data().c">C:<span data-bind="text:data().c"></span> 
 
</div>

+0

這與我正在尋找的相似,我將接受它作爲答案,因爲我的問題很模糊。儘管如此,我已經編輯了我的原始文章,並且更加清晰,如果您有任何其他想法,我全都是耳朵!謝謝 :) –