2015-08-31 103 views
3

我想弄清楚如何在嵌套深度大於2級的D3應用程序中更新嵌套數據。讓我們從我的代碼開始。更新嵌套數據

這是當頁面準備就緒時的jQuery處理程序。

$(function() { 
    var data = createDataSet(); 
    updateD3(data); 

    setTimeout(function() { 
     var dataAgain = createDataSet(); 
     updateD3(dataAgain); 
    }, 5000); 
}); 

這裏是更新功能。

function updateD3(data) { 
    var level1 = d3 
     .select('body') 
     .selectAll('div.level-1') 
     .data(data); 

    // UPDATE existing data. 
    level1 
     .text(function (d) { return d.nameLevelOne + '-'; }) 
     .selectAll('div.level-2') 
     .data(function (d) { return d.valuesLevelOne; }) 
     .text(function (d) { return d.nameLevelTwo + '-'; }) 
     .selectAll('div.level-3') 
     .data(function (d) { return d.valuesLevelTwo; }) 
     .text(function (d) { return d.nameLevelThree + ' ' + d.count + '-'; }); 

    // CREATE new data. 
    level1 
    .enter() 
     .append('div') 
     .attr('class', 'level-1') 
     .text(function (d) { return d.nameLevelOne; }) 
     .selectAll('div') 
     .data(function (d) { return d.valuesLevelOne; }) 
    .enter() 
     .append('div') 
     .attr('class', 'level-2') 
     .text(function (d) { return d.nameLevelTwo; }) 
     .selectAll('div') 
     .data(function (d) { return d.valuesLevelTwo; }) 
    .enter() 
     .append('div') 
     .attr('class', 'level-3') 
     .text(function (d) { return d.nameLevelThree + ' ' + d.count; }); 

    // REMOVE deleted data. 
    level1 
    .exit() 
     .selectAll('div') 
     .transition() 
     .style('opacity', 0) 
     .remove(); 
} 

這裏是數據創建功能,它也記錄了數據的結構。

function createDataSet() { 
     return [ 
     { 
      nameLevelOne: 'A', 
      valuesLevelOne: [{ 
       nameLevelTwo: 'AA', 
       valuesLevelTwo: [ 
        { 
         nameLevelThree: 'AAA', 
         count: Math.random() * 100 
        } 
       ] 
      }] 
     }, 
     { 
      nameLevelOne: 'B', 
      valuesLevelOne: [{ 
       nameLevelTwo: 'BB', 
       valuesLevelTwo: [ 
        { 
         nameLevelThree: 'BBB', 
         count: Math.random() * 100 
        } 
       ] 
      }] 
     } 
    ]; 
} 

當我在瀏覽器中運行此代碼時,第一個調用是完美的。它顯示了這一點:

A 
AA 
AAA 24.26636815071106 
B 
BB 
BBB 37.17236865777522 

如果將5秒後和新的數據集被創建並傳遞到另一個呼叫,則輸出變爲這樣:

A- 
B- 

這不是我所期望的輸出。我沒想到DOM的任何部分都會被銷燬。實質上,我預計AAABBB的數字會更新爲新值。

這是怎麼發生的?我如何只更新與更新的數據的DOM?

我已經查看並瀏覽了互聯網尋找解決方案,但幾乎每個「嵌套」數據示例實際上只有2層深,或者如果數據深度超過2層,則示例沒有代碼演示更新數據。

任何幫助非常感謝,尤其是在大約6個小時後,我的頭撞牆對此。

回答

3

你需要讓每一級多次選擇而不是一次的,即像

var level1 = selection.data(...); 
level1.enter()... 
level1.exit()... 
level1.... 

var level2 = level1.selectAll(...).data(...); 
level2.enter()... 
level2.exit()... 
level2... 

var level3 = level2.selectAll(...).data(...); 
// etc 

當你正在做的選擇和數據多次綁定,選擇相互影響,你會得到選擇中的錯誤元素。

+0

應該給每個'.data(...)'調用什麼?我相信'level1'調用應該被賦予原始數據,但是給定'level2'和'level3'的函數分別返回'd.valuesLevelOne'和'd.valuesLevelTwo'。 – kevin628

+0

是的,確切地說。和你當前的代碼一樣。 –

+0

我現在已經進一步了。我沒有注意到,你必須綁定數據,然後'輸入',然後'退出',然後'更新'**每級**。現在唯一的問題是,如果我更改數據並執行更新,則「B」,「BB」和「BBB」部分消失。有什麼想法嗎?以下是我的代碼的工作版本:https://jsfiddle.net/r2xt0w2k/ – kevin628