2015-03-31 51 views
4

我正在用包含數組值的子div填充div。在第一階段,該陣列是這樣的:D3 - 正確的更新元素數量,但錯誤值

arr_subpop_unique = ["CPL", "NAP", "NPL", "SAP", "SPL", "TPL", "UMW", "WMT", "XER"] 

我的選擇輸入/更新/退出看起來是這樣的:

var sizemapHeader = d3.select("#d3-sizemap-hr").selectAll("div") 
     .data(arr_subpop_unique) 

    sizemapHeader.enter().append("div") 
     .attr("class", "sizemap-hr-title ellipsis scroll_on_hover") 
     .html(function(d,i){ return d; }); 

    sizemapHeader.exit().remove(); 

這工作得很好,讓我對含有字符串中每個元素的股利。

當我再次運行該功能,我的數據陣列更新此:

arr_subpop_unique = ["MAN_MADE", "NATURAL"] 

更新返回兩個div,但是,它們含有「CPL」和「NAP」(索引值0和1)。有人可以解釋爲什麼這不會用「MAN_MADE」和「NATURAL」代替前兩個標記嗎?

感謝您的幫助......試圖讓輸入/更新/出口數據D3加入的竅門!

回答

3

看看"General update pattern"
我想你不會觸發D3的升級選擇

var sizemapHeader = 
d3.select("#d3-sizemap-hr").selectAll("div") 
    .data(arr_subpop_unique) 

sizemapHeader 
.enter() 
    .append("div") 
    .attr("class", "sizemap-hr-title ellipsis scroll_on_hover") 

sizemapHeader 
    .html(function(d,i){ return d; }); 

sizemapHeader 
.exit() 
    .remove(); 
+0

知道了......我必須小心方法鏈。我記得讀過這些。弄清楚這需要多長時間是很了不起的,但一旦得到它就是多麼簡單。 – thefreeline 2015-03-31 02:20:44

+0

不錯!玩的開心! – Plato 2015-03-31 02:26:10

+0

要有更多的樂趣;-) – thefreeline 2015-03-31 02:33:53

3

只需提供有關@Plato提供的答案不同的看法...

在某些情況下,你可能希望更改的數據被識別爲「新」,即。成爲enter選擇的一部分,而不僅僅是update的一部分。在你的例子中,它被認爲是update選擇的一部分,因爲你的數據被綁定到基於索引的DOM元素(這是默認值)。您可以通過將第二個參數傳遞給data調用來更改此行爲。

更多信息請參見https://github.com/mbostock/d3/wiki/Selections#data。它被稱爲key的論點。

下面是一個例子:

var sizemapHeader = d3.select("#d3-sizemap-hr").selectAll("div") 
    .data(arr_subpop_unique, function(d, i) { return d; }); 

sizemapHeader.enter().append("div") 
    .attr("class", "sizemap-hr-title ellipsis scroll_on_hover") 
    .html(function(d,i){ return d; }); 

sizemapHeader.exit().remove(); 

的第二個參數的data函數調用現在將確保數據由值綁定到DOM元素,而不是通過在陣列中的索引。

當您下一次使用新數據調用函數時,當前未綁定到DOM元素的任何值都將被視爲新的並且是enter選擇的一部分。

這兩種情況都很有用,具體取決於您試圖實現的目標。

+2

不錯......節點的存在不足以將其限定爲更新節點:它必須具有正確的數據綁定。這將強制新數據進入輸入選擇,它接收html。如果任何傳入數據與現有節點相匹配,則沒有問題:原始html已被保留。不浪費重寫DOM元素。這讓我想到應該始終使用密鑰。如果有一些現有的div帶有文本,那麼你甚至可以將它調整爲'return d || this.innerHTML;' – 2015-03-31 13:00:25

+0

我一般會發現,當我更新數據時,比方說向數組或類似項添加新的數據條目,我一直想使用'key'函數,否則最終會得到數據跳過這個位置並且轉換似乎並不平滑,特別是如果您碰巧也正在更改數據數組中元素的數量。也就是說,有很多示例沒有必要使用'key'函數,所以在這裏有選項是很好的。 – 2015-03-31 13:33:29

+0

是的,邁克·博斯托克談論[對象恆常性](http://bost.ocks.org/mike/constancy/),雖然我認爲這是一個奇怪的例子,我明白他的意思。我正在努力克服這些對象的缺陷行爲,但是,如果我按照你的建議使用關鍵函數,那麼我的所有擔憂都是沒有意義的。一切都表現得很合理。所以,這就是我喜歡它的原因。 – 2015-03-31 13:57:28

5

值得一提的是,鏈接有點不對稱,因爲enter()有融入更新選擇的副作用。這意味着,如果您在append()之後將更新選項添加​​到更新選項,它們也將添加到輸入節點上。另一方面,更新選擇不會合併到輸入選擇中。因此,在enter()之後鏈接的任何功能只會在輸入選擇中出現。

在OP問題的情況下,有兩個更新節點和零入口節點。因此,HTML將添加到不存在的輸入節點上,並且兩個更新節點的HTML不會更新。

所以,是的,這個工程......

var sizemapHeader = d3.select("#d3-sizemap-hr").selectAll("div") 
      .data(arr_subpop_unique) 

//ENTER 
sizemapHeader 
.enter() 
    .append("div") 
     .attr("class", "sizemap-hr-title ellipsis scroll_on_hover") 
//UPDATE 
sizemapHeader 
    .html(function (d, i) { return d; }) 

//EXIT 
sizemapHeader 
.exit() 
    .remove(); 

但這並不...

var sizemapHeader = d3.select("#d3-sizemap-hr").selectAll("div") 
      .data(arr_subpop_unique) 

//ENTER 
//sizemapHeader 
    .enter() 
    .append("div") 
     .attr("class", "sizemap-hr-title ellipsis scroll_on_hover") 

//UPDATE 
sizemapHeader 
     .html(function (d, i) { return d; }) 

//EXIT 
sizemapHeader 
.exit() 
    .remove(); 

這打破了最初的更新(當更新選擇爲空) ...

var sizemapHeader = d3.select("#d3-sizemap-hr").selectAll("div") 
      .data(arr_subpop_unique) 

//UPDATE 
sizemapHeader 
    .html(function (d, i) { return d; }) 

//ENTER 
sizemapHeader 
.enter() 
    .append("div") 
     .attr("class", "sizemap-hr-title ellipsis scroll_on_hover") 

//EXIT 
sizemapHeader 
.exit() 
    .remove(); 

當你跟蹤你的代碼,你會看到的sizemapHeader變化後的值對它調用。當您將追加 或插入

原因是埋在維基...

的輸入選擇併入更新選擇。分開將更新選擇應用於輸入和更新選擇,而不是將相同的運算符應用於更新選擇後,現在可以在輸入節點後僅將其應用於 更新選擇。如果您發現自己刪除整個選區的元素而僅重新插入其中的大部分元素,則可以使用 代替。例如:

var update_sel = svg.selectAll("circle").data(data) 
update_sel.attr(/* operate on old elements only */) 
update_sel.enter().append("circle").attr(/* operate on new elements only */) 
update_sel.attr(/* operate on old and new elements */) 
update_sel.exit().remove() /* complete the enter-update-exit pattern */ 
+0

很好的解釋,我一直覺得這很直觀,但是隨着你的解釋和維基的摘錄,我真的不知道爲什麼我只是直覺地想到這一點。無論如何,這似乎是一個相對較新的'd3'用戶的一個關鍵點,所以很高興看到另一個解釋,尤其是對於這些示例。 – 2015-03-31 13:31:44

+0

感謝您在wiki上調用本節。出於某種原因,這對我來說並不是很直觀(我還是比較新的),但這確實有助於澄清事情。看起來,我一直對wiki的描述方式進行很多操作,「刪除整個選擇的元素只是爲了重新插入大部分元素」。理解這將有助於我邁出下一步。非常感激! – thefreeline 2015-03-31 14:42:59