Qualcuno può spiegare la differenza tra datum () e data () in D3.js? Vedo entrambi in uso e non sono sicuro del motivo per cui dovresti scegliere uno rispetto all'altro?
Qualcuno può spiegare la differenza tra datum () e data () in D3.js? Vedo entrambi in uso e non sono sicuro del motivo per cui dovresti scegliere uno rispetto all'altro?
Risposte:
Ho trovato la risposta corretta qui dallo stesso Mike:
D3 - come gestire le strutture dati JSON?
Se si desidera associare i dati a un singolo elemento SVG, utilizzare
(...).data([data])
o
(...).datum(data)
Se si desidera associare i dati a più elementi SVG
(...).data(data).enter().append("svg")
.....
enter()
, d3 collegherà il resto degli elementi dell'array con elementi SVG appena creati.
Dopo aver esaminato un po 'questo, ho scoperto che le risposte qui su SO non sono complete in quanto coprono il caso solo quando invochi selection.data
e selection.datum
con un data
parametro di input . Anche in quello scenario, i due si comportano diversamente se la selezione è un singolo elemento rispetto a quando contiene più elementi. Inoltre, entrambi questi metodi possono anche essere invocati senza alcun argomento di input al fine di interrogare i dati / datum associati nella selezione, nel qual caso si comportano nuovamente in modo diverso e restituiscono cose diverse.
Edit - Ho inviato una risposta un po 'più dettagliata a questa domanda qui , ma il post qui sotto praticamente cattura tutti i punti chiave per quanto riguarda i due metodi e come si differenziano gli uni dagli altri.
Quando si fornisce data
come argomento di input
selection.data(data)
tenterà di eseguire un data-giunzione tra gli elementi della data
matrice con la selezione conseguente creazione di enter()
, exit()
e update()
selezioni che si può successivamente operare. Il risultato finale di questo è se si passa in un array data = [1,2,3]
, si tenta di unire ogni singolo elemento di dati (cioè datum) con la selezione. Ogni elemento della selezione avrà solo un singolo elemento di riferimento data
associato ad esso.
selection.datum(data)
ignora del tutto il processo di unione dei dati. Ciò assegna semplicemente l'insieme data
a tutti gli elementi della selezione nel suo insieme senza dividerlo come nel caso dei join di dati. Quindi, se vuoi associare un intero array data = [1, 2, 3]
ad ogni elemento DOM nel tuo selection
, allora selection.datum(data)
raggiungerai questo obiettivo.
Avvertenza: molte persone credono che
selection.datum(data)
sia equivalenteselection.data([data])
ma questo è vero solo seselection
contiene un singolo elemento . Seselection
contiene più elementi DOM,selection.datum(data)
associerà l'interodata
a ogni singolo elemento nella selezione. Al contrario,selection.data([data])
lega solo l'interodata
al primo elemento inselection
. Ciò è coerente con il comportamento di unione dei dati diselection.data
.
Quando non viene fornito alcun data
argomento di input
selection.data()
prenderà il dato associato per ciascun elemento nella selezione e li combinerà in un array che viene restituito. Quindi, se il vostro selection
comprende 3 elementi DOM con i dati "a"
, "b"
e "c"
tenuto a ciascun rispettivamente selection.data()
i rendimenti ["a", "b", "c"]
. È importante notare che se selection
è un singolo elemento con (a titolo esemplificativo) il dato "a"
associato ad esso, allora selection.data()
ritornerà ["a"]
e non "a"
come alcuni potrebbero aspettarsi.
selection.datum()
ha senso solo per una singola selezione in quanto è definita come la restituzione del riferimento associato al primo elemento della selezione. Quindi nell'esempio sopra con la selezione composta da elementi DOM con dato associato di "a"
, "b"
e "c"
, selection.datum()
ritornerebbe semplicemente "a"
.
Si noti che anche se
selection
ha un singolo elementoselection.datum()
eselection.data()
restituisce valori diversi. Il primo restituisce il dato associato per la selezione ("a"
nell'esempio sopra) mentre il secondo restituisce il dato associato all'interno di un array (["a"]
nell'esempio sopra).
Si spera che ciò aiuti a chiarire come selection.data
e selection.datum()
differire l'uno dall'altro sia quando si forniscono dati come argomento di input sia quando si esegue una query per l'origine associata non fornendo alcun argomento di input.
PS: il modo migliore per capire come funziona è iniziare con un documento HTML vuoto in Chrome e aprire la console e provare ad aggiungere alcuni elementi al documento e quindi iniziare a legare i dati usando selection.data
e selection.datum
. A volte, è molto più facile "brontolare" qualcosa facendo piuttosto che leggendo.
Ecco alcuni buoni link:
Buona discussione su D3 "data ()": capire come D3.js lega i dati ai nodi
Per quest'ultimo:
# selection.data([values[, key]])
Unisce la matrice di dati specificata con la selezione corrente. I valori specificati sono una matrice di valori di dati, ad esempio una matrice di numeri o oggetti o una funzione che restituisce una matrice di valori.
...
# selection.datum([value])
Ottiene o imposta i dati associati per ciascun elemento selezionato. A differenza del metodo selection.data, questo metodo non calcola un join (e quindi non calcola le selezioni di entrata e uscita).
Penso che la spiegazione fornita da HamsterHuey sia la migliore finora. Per espanderlo e dare una rappresentazione visiva delle differenze, ho creato un documento di esempio che illustra almeno parte delle differenze tra data
e datum
.
La risposta che segue è più un'opinione derivata dall'uso di questi metodi, ma sono felice di essere corretto se sbaglio.
Questo esempio può essere eseguito sotto o in questo violino .
const data = [1,2,3,4,5];
const el = d3.select('#root');
el
.append('div')
.classed('a', true)
.datum(data)
.text(d => `node => data: ${d}`);
const join= el
.selectAll('div.b')
.data(data);
join
.enter()
.append('div')
.classed('b', true)
.text((d, i) => `node-${i + 1} => data: ${d}`)
penso che datum
sia più semplice da capire poiché non fa un join, ma ovviamente questo significa anche che ha diversi casi d'uso.
Per me una grande differenza - anche se ce ne sono altre - è il fatto che data
è solo il modo naturale di fare (live) aggiornamenti su un grafico d3, poiché l'intero schema enter / update / exit lo rende semplice, una volta ottenuto.
datum
d'altra parte mi sembra più adatto per le rappresentazioni statiche. Nell'esempio seguente, ad esempio, ho potuto ottenere lo stesso risultato il mio looping sull'array originale e l'accesso ai dati per indice in questo modo:
data.map((n, i) => {
el
.append('div')
.classed('a', true)
.datum(data)
.text(d => `node-${n} => data: ${d[i]}`);
});
Provalo qui: https://jsfiddle.net/gleezer/e4m6j2d8/6/
Ancora una volta, penso che questo sia molto più facile da capire mentre ti liberi dall'onere mentale derivante dal modello di invio / aggiornamento / uscita, ma non appena dovrai aggiornare o modificare la selezione, sarà sicuramente meglio ricorrere a .data()
.
const data = [1,2,3,4,5];
const el = d3.select('#root');
el
.append('div')
.classed('a', true)
.datum(data)
.text(d => `node => data: ${d}`);
const join= el
.selectAll('div.b')
.data(data);
join
.enter()
.append('div')
.classed('b', true)
.text((d, i) => `node-${i + 1} => data: ${d}`)
/* Ignore all the css */
html {
font-family: arial;
}
.l {
width: 20px;
height: 20px;
display: inline-block;
vertical-align: middle;
margin: 10px 0;
}
.l-a {
background: #cf58e4;
}
.l-b {
background: #42e4e4;
}
.a {
border-bottom: 2px solid #cf58e4;
}
.b {
border-bottom: 2px solid #42e4e4;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.6.0/d3.min.js"></script>
<div style="margin-bottom: 20px;">
<span class="l l-a"></span> .datum() <br />
<span class="l l-b"></span> .data()
</div>
<div id="root"></div>