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?
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?
Odpowiedzi:
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")
.....
enter(), d3 wiąże resztę elementów tablicy z nowo utworzonymi elementami SVG.
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, że
selection.datum(data)jest to równoważne,selection.data([data])ale jest to prawdą tylko wtedy, gdyselectionzawiera 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ść zdatapierwszym 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 elementselection.datum()iselection.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.
Oto kilka dobrych linków:
Dobra dyskusja na temat D3 „data ()”: zrozumienie, w jaki sposób D3.js wiąże dane z węzłami
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).
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>