2016-01-27 79 views
3

使用knockout.mapping我嘗試從JSON映射到ko對象。當試圖使用更高級的映射選項解決方案時,我經常得到Uncaught TypeError: g is not a function。我試圖弄清楚什麼是問題,但我仍然感到困惑。爲什麼knockout.mapping在某些數據結構上失敗?

可以說我有很簡單的模型:

var data1 = { // works 
    a: "a", 
    b: [ 
    { b1: "v1" }, 
    { b2: "v2" } 
    ] 
}; 

現在消費這個優良樣板工程這樣的:

function viewModel (data) { 
    var self = this; 
    var a = ko.mapping.fromJS(data, { observe: "a"}); 

    return a; 
} 

var vm1 = viewModel(data1); // works 

我在我的模型的兩個屬性(ab),但我只需要a即可觀察,而b應該只複製到視圖模型。

可悲的是它不工作這麼好,如果數據結構變得更深:

var data1 = { // works 
    a: "a", 
    b: [ 
    { b1: "v1" }, 
    { b2: "v2" } 
    ] 
}; 

var data2 = { // Uncaught TypeError: g is not a function 
    a: "a", 
    b: [ 
    { b1: { name: "v1" } }, 
    { b2: { name: "v2" } } 
    ] 
}; 

var data3 = { // Uncaught TypeError: g is not a function 
    a: "a", 
    b1: { name: "v1" }, 
    b2: { name: "v2" } 
}; 

var data4 = { // works 
    a: "a", 
    b1: "v1", 
    b2: "v2" 
}; 

var data5 = { // works 
    a: "a", 
    b1: ["1::v1", "2::v1"], 
    b2: ["1::v2", "2::v2"] 
}; 

function viewModel (data) { 
    var self = this; 
    var a = ko.mapping.fromJS(data, { observe: "a"}); 

    return a; 
} 

var vm1 = viewModel(data1); // works 
var vm2 = viewModel(data2); // Uncaught TypeError: g is not a function 
var vm3 = viewModel(data3); // Uncaught TypeError: g is not a function 
var vm4 = viewModel(data4); // works 
var vm5 = viewModel(data5); // works 

這似乎令人費解的是複製一些結構工程和其他不。我明白,當樹中的某處存在多層哈希時,該問題會跳轉。

這是所需的行爲還是我在這裏有什麼問題?爲什麼複製一些結構的作品,而其他不是?

回答

5

我已經成功地重現您提到的問題:

var data1 = { // works 
 
    a: "a", 
 
    b: [ 
 
    { b1: "v1" }, 
 
    { b2: "v2" } 
 
    ] 
 
}; 
 

 
var data2 = { // Uncaught TypeError: g is not a function 
 
    a: "a", 
 
    b: [ 
 
    { b1: { name: "v1" } }, 
 
    { b2: { name: "v2" } } 
 
    ] 
 
}; 
 

 
function viewModel (data) { 
 
    var self = this; 
 
    var a = ko.mapping.fromJS(data, { observe: ["a"]}); 
 
    return a; 
 
} 
 

 
var vm1 = viewModel(data1); // works 
 
var vm2 = viewModel(data2); // Uncaught TypeError: g is not a function
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-debug.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>

正如你所看到的,我的攝製我既包括庫的非精縮版。我走進它的錯誤,這是在這裏,在這個代碼:

if(options.observe.length > 0 && ko.utils.arrayIndexOf(options.observe, fullPropertyName) == -1) 
{ 
    mappedRootObject[indexer] = value(); // <---- THIS LINE 
    options.copiedProperties[fullPropertyName] = true; 
    return; 
} 

這行讓我覺得奇怪,因爲通常與KO你需要明確需要「解包」的價值觀,如果你不確定,如果他們是普通的價值觀或可觀察的價值觀。

於是我來到了the relevant source code on Github,但讓我驚訝的是,從CDNJS版本上面的代碼是不存在,這是不同的:

if(options.observe.length > 0 && ko.utils.arrayIndexOf(options.observe, fullPropertyName) == -1) 
{ 
    mappedRootObject[indexer] = ko.utils.unwrapObservable(value); // <-- DIFFERENT 
    options.copiedProperties[fullPropertyName] = true; 
    return; 
} 

這行是我希望它成爲的方式。

然後,the most recent debug build再次有bug /第一個版本。

然後再進一步挖掘,我看到有issue #137正是這個問題。這個問題以我達到的相同結論結束:2.4.1構建中未包含修復程序。不會很快有新的版本:正如你在the project's readme中看到的,這個項目目前沒有被維護。底線:您需要解決這種情況,或者創建您自己的定製構建映射,修復此問題。

+0

謝謝!你的答案是徹底的,足夠的。我現在可能會停止用我的頭撞牆...... –

1

您是否考慮定義自定義對象構造?詳細信息可以在ko文檔的advanced section in "The mapping plugin" page中找到。

對於映射到/來自的JSON對象的不同情況,該文檔中包含了相當多的選項。

相關問題