Apa perbedaan D3 datum vs data?

199

Adakah yang bisa menjelaskan perbedaan antara datum () dan data () di D3.js? Saya melihat keduanya digunakan dan saya tidak yakin mengapa Anda harus memilih yang satu dari yang lain?

josephmisiti
sumber

Jawaban:

164

Saya menemukan jawaban yang benar di sini dari Mike sendiri:

D3 - bagaimana menangani struktur data JSON?

Jika Anda ingin mengikat data Anda ke elemen SVG tunggal, gunakan

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

atau

(...).datum(data)

Jika Anda ingin mengikat data Anda ke beberapa elemen SVG

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

.....

josephmisiti
sumber
Terima kasih untuk ini! fakta bahwa Anda memasukkan data ([data]) dan array hanya membantu saya menyadari bug yang tidak dapat saya ketahui selama seminggu terakhir! Terima kasih banyak ... selalu hal-hal bodoh yang salah.
Adam
22
data () melakukan gabung, datum () tidak.
s3-4v
Hanya perlu diingat, jika ada lebih banyak elemen array data daripada elemen SVG saat mengikat data enter(), d3 akan mengikat elemen array lainnya dengan elemen SVG yang baru dibuat.
aslantorret
49

Setelah melihat ini sedikit, saya telah menemukan bahwa jawaban di sini pada SO tidak lengkap karena mereka hanya membahas kasus ketika Anda memohon selection.datadan selection.datumdengan dataparameter input . Bahkan dalam skenario itu, keduanya berperilaku berbeda jika seleksi adalah elemen tunggal versus ketika mengandung banyak elemen. Selain itu, kedua metode ini juga dapat dipanggil tanpa argumen input apa pun untuk meminta data / datum terikat dalam seleksi, dalam hal ini mereka sekali lagi berperilaku berbeda dan mengembalikan hal-hal yang berbeda.

Sunting - Saya memposting jawaban yang sedikit lebih terperinci untuk pertanyaan ini di sini , tetapi posting di bawah ini cukup banyak menangkap semua poin kunci mengenai dua metode dan bagaimana mereka berbeda satu sama lain.

Saat memasok data sebagai argumen input

  • selection.data(data)akan berusaha melakukan penggabungan data antara elemen-elemen dataarray dengan seleksi yang menghasilkan pembuatan enter(), exit()dan update()seleksi yang selanjutnya dapat Anda operasikan. Hasil akhir dari ini adalah jika Anda meneruskan dalam array data = [1,2,3], upaya dilakukan untuk bergabung dengan setiap elemen data individu (yaitu datum) dengan seleksi. Setiap elemen dari seleksi hanya akan memiliki satu elemen datum yang dataterikat padanya.

  • selection.datum(data)melewati proses penggabungan data sekaligus. Ini hanya menetapkan keseluruhan datauntuk semua elemen dalam pemilihan secara keseluruhan tanpa membaginya seperti dalam kasus data-bergabung. Jadi jika Anda ingin mengikat seluruh array data = [1, 2, 3]ke setiap elemen DOM di Anda selection, maka selection.datum(data)akan mencapai ini.

Peringatan: Banyak orang percaya ituselection.datum(data)setara denganselection.data([data])tetapi ini hanya benar jika selection mengandung satu elemen . Jikaselectionmengandung beberapa elemen DOM, makaselection.datum(data)akan mengikat keseluruhandatauntuk setiap elemen tunggal dalam seleksi. Sebaliknya,selection.data([data])hanya mengikat keseluruhandata elemen pertama diselection. Ini konsisten dengan perilaku data-joinselection.data.

Saat memasok tidak ada dataargumen input

  • selection.data()akan mengambil datum terikat untuk setiap elemen dalam seleksi dan menggabungkannya ke dalam array yang dikembalikan. Jadi, jika Anda selectionmenyertakan 3 elemen DOM dengan data "a", "b"dan "c"terikat masing-masing, selection.data()kembali ["a", "b", "c"]. Penting untuk dicatat bahwa jika selectionmerupakan elemen tunggal dengan (sebagai contoh) datum "a"terikat padanya, maka selection.data()akan kembali ["a"]dan tidak "a"seperti yang diperkirakan beberapa orang.

  • selection.datum()hanya masuk akal untuk satu seleksi karena didefinisikan sebagai mengembalikan datum yang terikat ke elemen pertama seleksi. Jadi dalam contoh di atas dengan pemilihan yang terdiri dari elemen DOM dengan datum terikat "a", "b"dan "c", selection.datum()hanya akan kembali "a".

Perhatikan bahwa meskipun selectionmemiliki elemen tunggal, selection.datum()dan selection.data()mengembalikan nilai yang berbeda. Yang pertama mengembalikan datum terikat untuk seleksi ( "a"dalam contoh di atas) sedangkan yang terakhir mengembalikan datum terikat dalam array ( ["a"]dalam contoh di atas).

Semoga ini membantu memperjelas bagaimana selection.datadan selection.datum()berbeda satu sama lain ketika memberikan data sebagai argumen input dan ketika meminta datum terikat dengan tidak memberikan argumen input.

PS - Cara terbaik untuk memahami cara kerjanya adalah mulai dengan dokumen HTML kosong di Chrome dan membuka konsol dan mencoba menambahkan beberapa elemen ke dokumen dan kemudian mulai mengikat data menggunakan selection.datadan selection.datum. Terkadang, jauh lebih mudah untuk "grok" sesuatu dengan melakukan daripada membaca.

HamsterHuey
sumber
HamsterHuey sudah menunjukkan ini, tetapi mungkin ini merupakan pengingat yang berguna untuk mengingat bahwa "datum" adalah singular dan "data" berbentuk jamak. Oleh karena itu .datum berlaku untuk informasi terkait elemen tunggal.
Visio Guy
42

Berikut ini beberapa tautan bagus:

Per yang terakhir:

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

Bergabung dengan array data yang ditentukan dengan pilihan saat ini. Nilai yang ditentukan adalah larik nilai data, seperti larik angka atau objek, atau fungsi yang mengembalikan larik nilai.

...

# selection.datum([value])

Mendapat atau menetapkan data terikat untuk setiap elemen yang dipilih. Berbeda dengan metode selection.data, metode ini tidak menghitung gabungan (dan dengan demikian tidak menghitung masuk dan keluar dari pilihan).

paulsm4
sumber
11
diberikan definisi-definisi tersebut - saya masih bingung mengapa Anda perlu / ingin menggunakan datum ()
josephmisiti
Satu lagi contoh yang mungkin membantu memperjelas: ngokevin.com/blog/d3 . CATATAN: 1) Definisi Kevin: "Datum adalah data yang diikat ke elemen." 2) Perhatikan bagaimana dalam contoh Kevin kami "menggabungkan" dataset dengan "data ()" ... tapi kami "menggunakan" subset dengan mereferensikan "datum ()".
paulsm4
5

Saya pikir penjelasan yang diberikan oleh HamsterHuey adalah yang terbaik sejauh ini. Untuk memperluas dan memberikan representasi visual dari perbedaan, saya membuat dokumen sampel yang menggambarkan setidaknya sebagian dari perbedaan antara datadan datum.

Jawaban di bawah ini lebih merupakan pendapat yang berasal dari menggunakan metode ini, tetapi saya senang bisa diperbaiki jika saya salah.

Contoh ini dapat dijalankan di bawah atau di Fiddle ini .

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

Saya pikir itu datumlebih mudah untuk dipahami karena tidak bergabung, tetapi tentu saja ini juga berarti memiliki kasus penggunaan yang berbeda.

Bagi saya satu perbedaan besar - walaupun ada lebih banyak - adalah kenyataan bahwa itu dataadalah cara alami untuk melakukan pembaruan (langsung) pada grafik d3, karena keseluruhan pola masuk / perbarui / keluar membuatnya mudah, setelah Anda mendapatkannya.

datumdi sisi lain menurut saya lebih cocok untuk representasi statis. Dalam contoh di bawah ini misalnya saya bisa mencapai hasil yang sama dengan pengulangan pada array asli dan mengakses data dengan indeks seperti ini:

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

Cobalah di sini: https://jsfiddle.net/gleezer/e4m6j2d8/6/

Sekali lagi, saya pikir ini adalah cara yang lebih mudah untuk dipahami karena Anda terbebas dari beban mental yang datang dari pola masuk / perbarui / keluar, tetapi segera setelah Anda perlu memperbarui atau mengubah pilihan Anda pasti akan lebih baik menggunakan .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
sumber