2012-08-17 87 views
2

The Knockout mapping plugin documentation有一個標題爲「使用唯一標識對象」鍵「」的部分。這描述瞭如何更新對象的一部分,然後只更新顯示的那部分,而不是完全替換部分修改的對象的所有屬性的顯示。這一切都在他們簡單的例子中出色地表現出來,我在這裏稍微修改了一下,使我的問題更加清晰。我的修改如下:敲除映射 - 使用鍵唯一標識嵌套對象

  1. 延遲2秒後用正確的名稱替換對象。

  2. 突出顯示不變的部分,所以你可以看到它實際上不會在更新發生時被替換。

1.簡單對象jsFiddle

<h1 data-bind="text: name"></h1> 
<ul data-bind="foreach: children"> 
    <li><span class="id" data-bind="text: id"></span> <span data-bind="text: name"></span></li> 
</ul> 

<script> 
var data = { 
    name: 'Scot', 
    children: [ 
     {id : 1, name : 'Alicw'} 
    ] 
}; 
var mapping = { 
    children: { 
     key: function(data) { 
      console.log(data); 
      return ko.utils.unwrapObservable(data.id); 
     } 
    } 
}; 
var viewModel = ko.mapping.fromJS(data, mapping); 
ko.applyBindings(viewModel); 

var range = document.createRange(); 
range.selectNode(document.getElementsByClassName("id")[0]); 
window.getSelection().addRange(range); 

setTimeout(function() { 
    var data = { 
     name: 'Scott', 
     children: [ 
      {id : 1, name : 'Alice'} 
     ] 
    }; 
    ko.mapping.fromJS(data, viewModel); 
}, 2000); 
</script> 

但是,什麼是我不明白是怎麼會達到同樣的行爲更爲複雜的嵌套的數據結構。在下面的例子中,我使用了上面的代碼並將數據包裝在一個列表中。我希望這與上面的行爲相同,但事實並非如此。整個顯示是由於一個屬性的變化而重做的。您可以看到這一點,因爲與上面的示例不同,數據更新後突出顯示會丟失。

2.更復雜的嵌套對象jsFiddle

<!-- ko foreach: parents --> 
    <h1 data-bind="text: name"></h1> 
    <ul data-bind="foreach: children"> 
     <li><span class="id" data-bind="text: id"></span> <span data-bind="text: name"></span></li> 
    </ul> 
<!-- /ko --> 

<script> 
var data = { 
    parents: [ 
     { 
      name: 'Scot', 
      children: [ 
       {id : 1, name : 'Alicw'} 
      ] 
     } 
    ] 
}; 
var mapping = { 
    children: { 
     key: function(data) { 
      console.log(data); 
      return ko.utils.unwrapObservable(data.id); 
     } 
    } 
}; 
var viewModel = ko.mapping.fromJS(data, mapping); 
ko.applyBindings(viewModel); 

var range = document.createRange(); 
range.selectNode(document.getElementsByClassName("id")[0]); 
window.getSelection().addRange(range); 

setTimeout(function() { 
    var data = { 
     parents: [ 
      { 
       name: 'Scott', 
       children: [ 
        {id : 1, name : 'Alice'} 
       ] 
      } 
     ] 
    }; 
    ko.mapping.fromJS(data, viewModel); 
}, 2000); 
</script> 

所以基本上要問什麼,我是,我怎麼能做出第二個例子一樣工作,第一,考慮到多個嵌套數據結構?你可以假設每個孩子的ID都是唯一的(所以如果我添加了除斯科特之外的另一位父母,他的孩子將以ID = 2等開始)。

回答

2

有趣的觀察和漂亮的報道。它似乎工作,如果你定義一個關鍵的父母以及孩子。試試這個小提琴:

http://jsfiddle.net/8QJe7/6/

它定義爲父母和孩子,這裏的父類的構造做它的子映射實例化視圖模型的功能。

+0

謝謝,這似乎工作,但我希望有一個更簡單和更直觀的方式,因爲它似乎很奇怪必須爲父母和孩子定義密鑰,即使它只用於孩子 - 任何想法爲什麼是這樣?另外,你知道如果多次調用ko.mapping.fromJS會有很大的性能損失嗎?我想這可能取決於上下文,是否有意義或者天真地更新所有內容? – dumbmatter 2012-08-19 23:41:46

+1

我還沒有深入到映射插件的內部,但我認爲有一個很好的理由,它需要能夠識別孩子的父母,因爲它通過對象和DOM元素的層次結構工作。重新性能 - 我的視圖模型層次結構大約有6層深度,全部實現爲可實例化的函數,這些函數使用像我的小提琴那樣的按鍵來創建子項。每個級別的兄弟姐妹的數量是高度可變的,但它執行得非常順利,可以在我的應用程序的實際使用參數內從上到下映射更新。每個應用程序將有所不同。 – 2012-08-20 00:10:56

+1

因爲各種複雜的原因,我確實開始做自己的映射過程 - 但最終我放棄了並重新考慮了我的應用程序邏輯,而是使用映射插件。我發現使用唯一鍵對嵌套對象和數組進行大量健壯的更新並不是一件容易的事情,而且他們對我認爲的那個插件做了很好的工作。 – 2012-08-20 00:14:55