Jaka jest różnica między danymi D3 a danymi?

199

Czy ktoś może wyjaśnić różnicę między datum () a data () w D3.js? Widzę, że oba są używane i nie jestem pewien, dlaczego powinieneś wybrać jedno z nich?

josephmisiti
źródło

Odpowiedzi:

164

Znalazłem tutaj poprawną odpowiedź od samego Mike'a:

D3 - jak radzić sobie ze strukturami danych JSON?

Jeśli chcesz powiązać swoje dane z jednym elementem SVG, użyj

(...).data([data])

lub

(...).datum(data)

Jeśli chcesz powiązać swoje dane z wieloma elementami SVG

(...).data(data).enter().append("svg")

.....

josephmisiti
źródło
Dziękuję Ci za to! fakt, że umieściłeś przekazywanie danych ([data]) i tablicę, pomógł mi zdiagnozować błąd, którego nie mogłem znaleźć w ostatnim tygodniu! Dziękuję bardzo ... zawsze takie głupie rzeczy, które są złe.
Adam
22
data () wykonuje łączenie, datum () nie.
s3-4v
Pamiętaj tylko, że w przypadku, gdy istnieje więcej elementów tablicy danych niż elementów SVG podczas wiązania danych enter(), d3 wiąże resztę elementów tablicy z nowo utworzonymi elementami SVG.
aslantorret
49

Po dokładnym przyjrzeniu się temu stwierdziłem, że odpowiedzi tutaj na SO nie są kompletne, ponieważ obejmują one tylko przypadek, gdy wywołujesz selection.datai selection.datumz dataparametrem wejściowym . Nawet w tym scenariuszu oba zachowują się inaczej, jeśli zaznaczenie jest pojedynczym elementem, a jeśli zawiera wiele elementów. Co więcej, obie te metody można również wywoływać bez żadnych argumentów wejściowych w celu przeszukiwania powiązanych danych / danych w zaznaczeniu, w którym to przypadku ponownie zachowują się inaczej i zwracają różne rzeczy.

Edit - napisałem nieco bardziej szczegółową odpowiedź na to pytanie tutaj , ale post poniżej dość dużo przechwytuje wszystkie najważniejsze punkty dotyczące tych dwóch metod i jak różnią się one od siebie.

Podając data jako argument wejściowy

  • selection.data(data)dokładają wszelkich starań, aby wykonać dane dołącz pomiędzy elementami datatablicy z wyboru, w wyniku utworzenia enter(), exit()oraz update()pozycje, które można następnie operować. Efektem końcowym tego jest, jeśli przejdziesz do tablicy data = [1,2,3], podejmowana jest próba połączenia każdego elementu danych (tj. Układu odniesienia) z zaznaczeniem. Każdy element zaznaczenia będzie miał związany tylko jeden element odniesienia data.

  • selection.datum(data)całkowicie pomija proces łączenia danych. To po prostu przypisuje całość datawszystkim elementom zaznaczenia jako całości, bez dzielenia go, jak w przypadku łączenia danych. Więc jeśli chcesz powiązać całą tablicę data = [1, 2, 3]z każdym elementem DOM w twoim selection, wtedy selection.datum(data)to osiągniesz.

Ostrzeżenie: wiele osób uważa, żeselection.datum(data)jest to równoważne,selection.data([data])ale jest to prawdą tylko wtedy, gdy selection zawiera jeden element . Jeśliselectionzawiera wiele elementów DOM, wówczasselection.datum(data)wiąże całość zdatakażdym elementem w zaznaczeniu. W przeciwieństwie,selection.data([data])wiąże tylko całość zdata pierwszym elementem wselection. Jest to zgodne z zachowaniem łączenia danychselection.data.

Gdy nie datapodajesz argumentu wejściowego

  • selection.data()weźmie powiązane dane dla każdego elementu w zaznaczeniu i połączy je w zwracaną tablicę. Tak więc, jeśli selectionskłada się z 3 elementów DOM z danymi "a", "b"a "c"połączone ze sobą odpowiednio selection.data()zwrotów ["a", "b", "c"]. Ważne jest, aby zauważyć, że jeśli selectionjest to pojedynczy element z (na przykład) "a"związaną z nim datum , wówczas selection.data()powróci ["a"]i nie będzie, "a"jak niektórzy mogą się spodziewać.

  • selection.datum()ma sens tylko dla pojedynczego zaznaczenia, ponieważ jest zdefiniowany jako powrót układu odniesienia związanego z pierwszym elementem zaznaczenia. Tak więc w powyższym przykładzie z wyboru składający się z elementów DOM ze związanym z odniesienia "a", "b"i "c", selection.datum()po prostu wrócić "a".

Zauważ, że nawet jeśli selectionma jeden element selection.datum()i selection.data()zwracaj różne wartości. Pierwszy zwraca związany punkt odniesienia dla wyboru ( "a"w powyższym przykładzie), podczas gdy drugi zwraca związany punkt odniesienia w tablicy ( ["a"]w powyższym przykładzie).

Mam nadzieję, że to pomaga wyjaśnić, w jaki sposób selection.datai selection.datum()różnią się od siebie zarówno w przypadku udostępniania danych jako argument wejściowy i podczas odpytywania dla związanego odniesienia nie dostarczając żadnych argumentów wejściowych.

PS - Najlepszym sposobem na zrozumienie, jak to działa, jest rozpoczęcie od pustego dokumentu HTML w Chrome i otwarcie konsoli i próba dodania kilku elementów do dokumentu, a następnie rozpoczęcie wiązania danych za pomocą selection.datai selection.datum. Czasami o wiele łatwiej „coś” zrobić, robiąc, niż czytając.

Chomik
źródło
HamsterHuey już to pokazał, ale pomocne może być przypomnienie, że „dane” są w liczbie pojedynczej, a „dane” w liczbie mnogiej. Dlatego .datum dotyczy informacji powiązanych z jednym elementem.
Visio Guy
42

Oto kilka dobrych linków:

Zgodnie z tym ostatnim:

# selection.data([values[, key]])

Łączy podaną tablicę danych z bieżącym wyborem. Podane wartości to tablica wartości danych, na przykład tablica liczb lub obiektów, lub funkcja zwracająca tablicę wartości.

...

# selection.datum([value])

Pobiera lub ustawia powiązane dane dla każdego wybranego elementu. W przeciwieństwie do metody selection.data, ta metoda nie oblicza złączenia (a zatem nie oblicza wejść i wyjść z selekcji).

paulsm4
źródło
11
biorąc pod uwagę te definicje - Jestem nadal mylone dlaczego byś kiedykolwiek potrzebują / chcą wykorzystywać układ odniesienia ()
josephmisiti
Jeszcze jeden przykład, który może pomóc w wyjaśnieniu : ngokevin.com/blog/d3 . UWAGI: 1) Definicja Kevina: „Daną odniesienia są dane powiązane z elementem”. 2) Zwróć uwagę, jak w przykładach Kevina „włączamy” zestaw danych do „data ()” ... ale „używamy” podzestawu, odwołując się do „datum ()”.
paulsm4
5

Myślę, że wyjaśnienie podane przez HamsterHuey jest jak dotąd najlepsze. Aby go rozwinąć i przedstawić wizualnie różnice, stworzyłem przykładowy dokument, który ilustruje przynajmniej część różnic między datai datum.

Poniższa odpowiedź jest bardziej opinią wynikającą z zastosowania tych metod, ale cieszę się, że mogę je poprawić, jeśli się mylę.

Ten przykład można uruchomić poniżej lub w tym skrzypce .

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}`)

Myślę, że datumłatwiej jest to uchwycić, ponieważ nie wykonuje łączenia, ale oczywiście oznacza to również, że ma różne przypadki użycia.

Dla mnie jedną wielką różnicą - choć jest ich więcej - to fakt, że datajest to naturalny sposób wykonywania aktualizacji (na żywo) na wykresie d3, ponieważ cały wzorzec wchodzenia / aktualizowania / wychodzenia sprawia, że ​​jest to proste, gdy tylko je dostaniesz.

datumz drugiej strony wydaje mi się, że lepiej nadaje się do przedstawień statycznych. W poniższym przykładzie mogę na przykład osiągnąć ten sam wynik, zapętlając oryginalną tablicę i uzyskując dostęp do danych przez indeks w ten sposób:

data.map((n, i) => {
 el
  .append('div')
  .classed('a', true)
  .datum(data)
  .text(d => `node-${n} => data: ${d[i]}`);
});

Wypróbuj tutaj: https://jsfiddle.net/gleezer/e4m6j2d8/6/

Ponownie myślę, że jest to o wiele łatwiejsze do uchwycenia, ponieważ uwalniasz się od mentalnego obciążenia wynikającego ze schematu wchodzenia / aktualizowania / wychodzenia, ale gdy tylko będziesz musiał zaktualizować lub zmienić wybór, na pewno lepiej będzie się uciekać .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>

Nobita
źródło