ใครช่วยอธิบายความแตกต่างระหว่าง datum () และ data () ใน D3.js ได้ไหม? ฉันเห็นทั้งการใช้งานและฉันไม่แน่ใจว่าทำไมคุณควรเลือกอันใดอันหนึ่ง
ใครช่วยอธิบายความแตกต่างระหว่าง datum () และ data () ใน D3.js ได้ไหม? ฉันเห็นทั้งการใช้งานและฉันไม่แน่ใจว่าทำไมคุณควรเลือกอันใดอันหนึ่ง
คำตอบ:
ฉันพบคำตอบที่ถูกต้องจากไมค์เอง:
D3 - วิธีจัดการกับโครงสร้างข้อมูล JSON?
หากคุณต้องการผูกข้อมูลของคุณกับองค์ประกอบ SVG เดียวให้ใช้
(...).data([data])
หรือ
(...).datum(data)
หากคุณต้องการผูกข้อมูลของคุณเข้ากับองค์ประกอบ SVG หลายรายการ
(...).data(data).enter().append("svg")
.....
enter()
กัน d3 จะผูกองค์ประกอบส่วนที่เหลือกับองค์ประกอบ SVG ที่สร้างขึ้นใหม่
หลังจากตรวจสอบเล็กน้อยฉันพบว่าคำตอบที่นี่บน SO นั้นไม่สมบูรณ์เนื่องจากครอบคลุมเฉพาะกรณีเมื่อคุณเรียกใช้selection.data
และselection.datum
มีdata
พารามิเตอร์อินพุต แม้ว่าในสถานการณ์นั้นทั้งสองจะทำงานต่างกันหากการเลือกเป็นองค์ประกอบเดียวกับเมื่อมีหลายองค์ประกอบ ยิ่งไปกว่านั้นวิธีการทั้งสองนี้ยังสามารถเรียกใช้โดยไม่มีข้อโต้แย้งอินพุตเพื่อสอบถามข้อมูล / ข้อมูลที่ถูกผูกไว้ในการเลือกซึ่งในกรณีนี้พวกเขาจะทำงานแตกต่างกันอีกครั้งและส่งคืนสิ่งต่าง ๆ
แก้ไข - ฉันโพสต์คำตอบโดยละเอียดเพิ่มเติมเล็กน้อยสำหรับคำถามนี้ที่นี่แต่โพสต์ด้านล่างค่อนข้างจับประเด็นสำคัญทั้งหมดเกี่ยวกับสองวิธีและความแตกต่างจากกันและกัน
เมื่อขาย data
เป็นอาร์กิวเมนต์ป้อนเข้า
selection.data(data)
จะพยายามที่จะดำเนินการข้อมูลร่วมระหว่างองค์ประกอบของdata
อาร์เรย์ที่มีให้เลือกในการสร้างผลของenter()
, exit()
และupdate()
เลือกที่คุณต่อมาสามารถทำงานบน ผลลัพธ์สุดท้ายของสิ่งนี้คือถ้าคุณส่งผ่านอาร์เรย์จะdata = [1,2,3]
มีการพยายามเข้าร่วมแต่ละองค์ประกอบข้อมูล (เช่นข้อมูล) กับการเลือก องค์ประกอบของการเลือกแต่ละรายการจะมีองค์ประกอบ datum เดียวที่data
ถูกผูกไว้กับมัน
selection.datum(data)
ข้ามกระบวนการเข้าร่วมข้อมูลโดยสิ้นเชิง สิ่งนี้จะกำหนดdata
องค์ประกอบทั้งหมดให้กับองค์ประกอบทั้งหมดในการเลือกโดยไม่แยกเป็นส่วน ๆ ในกรณีของการรวมข้อมูล ดังนั้นหากคุณต้องการที่จะผูกอาร์เรย์ทั้งหมดdata = [1, 2, 3]
ทุกองค์ประกอบ DOM ในของคุณselection
แล้วselection.datum(data)
จะประสบความสำเร็จนี้
คำเตือน:หลายคนเชื่อว่า
selection.datum(data)
จะเทียบเท่ากับselection.data([data])
แต่นี้เป็นจริงเฉพาะในกรณี ที่มีองค์ประกอบเดียวselection
หากselection
มีองค์ประกอบ DOM หลายรายการคุณselection.datum(data)
จะผูกองค์ประกอบทั้งหมดdata
กับทุกรายการในการเลือก ในทางตรงกันข้ามselection.data([data])
จะผูกองค์ประกอบทั้งหมดdata
เข้ากับองค์ประกอบแรกselection
เท่านั้นselection.data
ซึ่งสอดคล้องกับข้อมูลที่เข้าร่วมการทำงานของ
เมื่อไม่ได้ระบุdata
อาร์กิวเมนต์อินพุต
selection.data()
จะใช้ datum ที่ถูกผูกไว้สำหรับแต่ละองค์ประกอบในการเลือกและรวมเข้าไปในอาร์เรย์ที่ส่งคืน ดังนั้นถ้าคุณselection
มี 3 องค์ประกอบ DOM กับข้อมูล"a"
, "b"
และ"c"
ผูกไว้กับแต่ละตามลำดับผลตอบแทนselection.data()
["a", "b", "c"]
เป็นสิ่งสำคัญที่จะต้องทราบว่าหากselection
เป็นองค์ประกอบเดียวที่มี (ตามตัวอย่าง) ตัวเลขที่"a"
ผูกไว้กับมันจากนั้นselection.data()
จะกลับมา["a"]
และไม่"a"
เป็นไปตามที่บางคนคาด
selection.datum()
ทำให้เหมาะสมสำหรับการเลือกเดียวตามที่กำหนดไว้เป็นการส่งคืนข้อมูลที่โยงกับองค์ประกอบแรกของการเลือก ดังนั้นในตัวอย่างข้างต้นด้วยการเลือกประกอบด้วยองค์ประกอบ DOM กับตัวเลขที่ถูกผูกไว้ของ"a"
, "b"
และ"c"
, การกลับมาก็จะselection.datum()
"a"
โปรดทราบว่าแม้ว่าจะ
selection
มีองค์ประกอบเดียวselection.datum()
และselection.data()
ส่งกลับค่าที่แตกต่างกัน อดีตส่งกลับ datum ที่ถูกผูกไว้สำหรับการเลือก ("a"
ในตัวอย่างด้านบน) ในขณะที่หลังส่งคืน datum ที่ถูกผูกไว้ภายในอาร์เรย์ (["a"]
ในตัวอย่างด้านบน)
หวังว่าสิ่งนี้จะช่วยชี้แจงว่าselection.data
และselection.datum()
แตกต่างจากกันอย่างไรเมื่อให้ข้อมูลเป็นอาร์กิวเมนต์อินพุตและเมื่อทำการสืบค้น datum ที่ถูกผูกไว้โดยไม่ระบุอาร์กิวเมนต์อินพุตใด ๆ
PS - วิธีที่ดีที่สุดที่จะเข้าใจวิธีการทำงานนี้คือการเริ่มต้นด้วยเอกสาร HTML ว่างเปล่าใน Chrome และจะเปิดคอนโซลและลองเพิ่มองค์ประกอบไม่กี่เอกสารและจากนั้นเริ่มมีผลผูกพันข้อมูลโดยใช้และselection.data
selection.datum
บางครั้งมันง่ายกว่าที่จะ "grok" บางอย่างโดยการทำมากกว่าการอ่าน
นี่คือลิงค์ที่ดีบางส่วน:
การอภิปรายที่ดีเกี่ยวกับ D3 "data ()": ทำความเข้าใจว่า D3.js ผูกข้อมูลกับโหนดอย่างไร
ต่อหลัง:
# selection.data([values[, key]])
เข้าร่วมอาร์เรย์ของข้อมูลที่ระบุด้วยการเลือกปัจจุบัน ค่าที่ระบุคืออาร์เรย์ของค่าข้อมูลเช่นอาร์เรย์ของตัวเลขหรือวัตถุหรือฟังก์ชันที่ส่งคืนอาร์เรย์ของค่า
...
# selection.datum([value])
รับหรือตั้งค่าข้อมูลที่ถูกผูกไว้สำหรับแต่ละองค์ประกอบที่เลือก ซึ่งแตกต่างจากวิธี selection.data วิธีนี้ไม่ได้คำนวณการเข้าร่วม (และไม่คำนวณการเข้าและออกจากการเลือก)
ฉันคิดว่าคำอธิบายของ HamsterHuey นั้นดีที่สุดแล้ว เพื่อขยายมันและให้การแสดงออกของความแตกต่างฉันสร้างเอกสารตัวอย่างที่แสดงให้เห็นในส่วนที่น้อยที่สุดของความแตกต่างระหว่างและdata
datum
คำตอบด้านล่างนี้เป็นความเห็นที่มากขึ้นจากการใช้วิธีการเหล่านี้ แต่ฉันยินดีที่จะแก้ไขหากฉันผิด
ตัวอย่างนี้สามารถเรียกใช้ด้านล่างหรือในซอนี้
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}`)
ฉันคิดว่าdatum
มันง่ายกว่าที่จะเข้าใจเนื่องจากมันไม่ได้เข้าร่วม แต่แน่นอนว่านี่หมายความว่ามันมีกรณีการใช้ที่แตกต่างกัน
สำหรับฉันความแตกต่างที่สำคัญอย่างหนึ่ง - ถึงแม้ว่าจะมีมากกว่านั้นก็คือความจริงที่data
เป็นเพียงวิธีธรรมชาติในการอัปเดต (สด) บนแผนภูมิ d3 เนื่องจากรูปแบบการป้อน / การอัปเดต / ออกทั้งหมดทำให้มันง่ายขึ้นเมื่อคุณได้รับ
datum
ในทางตรงกันข้ามดูเหมือนว่าฉันจะเหมาะสำหรับการเป็นตัวแทนคงที่ ในตัวอย่างด้านล่างตัวอย่างเช่นฉันสามารถบรรลุผลเดียวกันลูปของฉันในอาร์เรย์เดิมและเข้าถึงข้อมูลตามดัชนีดังนี้:
data.map((n, i) => {
el
.append('div')
.classed('a', true)
.datum(data)
.text(d => `node-${n} => data: ${d[i]}`);
});
ลองที่นี่: https://jsfiddle.net/gleezer/e4m6j2d8/6/
อีกครั้งผมคิดว่านี่เป็นวิธีที่ง่ายต่อการเข้าใจที่คุณให้เป็นอิสระจากภาระทางจิตมาจากใส่ / ปรับปรุง / รูปแบบการออก .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>