HTML Academy · บทเรียน

รายการลากเพื่อจัดลำดับใหม่ภาคปฏิบัติ

สร้างรายการที่จัดลำดับใหม่ได้ด้วย Drag and Drop API

บทเรียน 4 จาก 413 ขั้นตอน

รายการลากเพื่อจัดลำดับใหม่ภาคปฏิบัติ เป็นบทเรียน HTML Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน HTML Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส HTML Academy มีบทเรียนทั้งหมด 4 บทเรียน

ภาพรวมรูปแบบ

หากต้องการสร้างรายการที่ลากเพื่อจัดลำดับใหม่ ให้ทุกรายการลากได้ จัดเก็บรหัสของรายการที่กำลังลากไว้ใน dataTransfer เมื่อเริ่มลาก และเมื่อวาง ให้แทรกองค์ประกอบที่ลากไว้ก่อนหรือหลังเป้าหมาย DOM และแบบจำลองจะยังสอดคล้องกัน หากสร้างลำดับใหม่จาก DOM หลังการวางแต่ละครั้ง

มาร์กอัป

แสดงผลรายการแบบแบน โดยให้ทุก li มี draggable="true" และ data-id การเก็บรหัสไว้บนองค์ประกอบทำให้ตัวจัดการการลากไม่จำเป็นต้องค้นหาที่เก็บสถานะแยกต่างหากเพื่อระบุรายการ เพราะองค์ประกอบนั้นเองเป็นแหล่งข้อมูลอ้างอิงหลัก

<ul id="list">
  <li draggable="true" data-id="1">Item 1</li>
  <li draggable="true" data-id="2">Item 2</li>
  <li draggable="true" data-id="3">Item 3</li>
</ul>

การเริ่มลากบันทึกแหล่งที่มา

เมื่อเริ่มลาก ให้จัดเก็บรหัสของรายการที่ลากไว้ใน dataTransfer และเพิ่มคลาส "dragging" เพื่อแสดงผลตอบสนองทางภาพ effectAllowed="move" บอกเบราว์เซอร์ว่านี่เป็นการจัดลำดับใหม่ ไม่ใช่การคัดลอก ดังนั้นเคอร์เซอร์และ dropEffect จึงสะท้อนการดำเนินการย้าย

list.addEventListener("dragstart", (e) => {
  const li = e.target.closest("li");
  if (!li) return;
  e.dataTransfer.setData("text/plain", li.dataset.id);
  e.dataTransfer.effectAllowed = "move";
  li.classList.add("dragging");
});

การลากผ่านอนุญาตให้วาง

รับฟังเหตุการณ์ที่รายการโดยใช้การมอบหมายเหตุการณ์ เรียก preventDefault และกำหนด dropEffect เป็น "move" ใช้ e.target.closest("li") เพื่อค้นหาแถวที่เคอร์เซอร์วางอยู่เหนือนั้น ทำให้ตัวจัดการเดียวกันทำงานกับรายการทั้งหมดได้

การคำนวณตำแหน่งแทรก

หากต้องการตัดสินใจว่ารายการที่ลากควรอยู่เหนือหรือใต้แถวที่เคอร์เซอร์วางอยู่ ให้เปรียบเทียบตำแหน่ง Y ของเคอร์เซอร์กับจุดกึ่งกลางแนวตั้งของแถว: const before = (e.clientY - rect.top) < rect.height / 2 ค่า before=true หมายถึงให้ใช้ insertBefore ส่วนค่า false หมายถึงให้ใช้ insertAfter

function getInsertBefore(target, clientY) {
  const rect = target.getBoundingClientRect();
  return clientY < rect.top + rect.height / 2;
}

การวางจัดลำดับ DOM ใหม่

ในตัวจัดการการวาง ให้ค้นหาองค์ประกอบที่กำลังลากด้วยรหัส และค้นหาแถวเป้าหมายใต้เคอร์เซอร์ เรียก list.insertBefore(dragged, target) หรือ list.insertBefore(dragged, target.nextSibling) โดยขึ้นอยู่กับว่าเคอร์เซอร์อยู่เหนือครึ่งใดของเป้าหมาย

การสิ้นสุดการลากล้างรูปแบบ

ไม่ว่าการวางจะสำเร็จหรือผู้ใช้จะกด Escape เหตุการณ์สิ้นสุดการลากจะเกิดขึ้นที่แหล่งลากเสมอ ใช้เหตุการณ์นี้เพื่อลบคลาส "dragging" และการเน้นเป้าหมายการวางทั้งหมด เพื่อให้รายการกลับสู่สถานะพร้อมใช้งาน

list.addEventListener("dragend", () => {
  list.querySelectorAll(".dragging, .over").forEach((el) => {
    el.classList.remove("dragging", "over");
  });
});

ตัวบ่งชี้ตำแหน่งวางแบบภาพ

แสดงเส้นบาง ๆ ณ ตำแหน่งที่รายการจะถูกวาง โดยใช้ pseudo-element ของ CSS บนแถวที่เคอร์เซอร์วางอยู่ และสลับด้วยคลาส "over-top" หรือ "over-bottom" ซึ่งตัวจัดการการลากผ่านกำหนดตามตำแหน่งเคอร์เซอร์ ผู้ใช้จะเห็นจุดแทรกก่อนปล่อยรายการ

การซิงค์แบบจำลอง

หลังการวาง ให้หาลำดับใหม่จาก DOM: const order = Array.from(list.children).map((li) => li.dataset.id) ส่งอาร์เรย์นั้นไปยังเซิร์ฟเวอร์หรือจัดเก็บไว้ในสถานะ อย่าพยายามดูแลดัชนีคู่ขนานกับ DOM เพราะดัชนีจะคลาดเคลื่อนเมื่อมีการลากอย่างรวดเร็ว

ทางเลือกด้วยแป้นพิมพ์

เพิ่มตัวจัดการปุ่มขึ้นและลงเพื่อย้ายรายการที่มีโฟกัสด้วย insertBefore ประกาศการย้ายผ่านพื้นที่ aria-live ("ย้ายรายการขึ้นไปยังตำแหน่งที่ 2") ผู้ใช้แป้นพิมพ์จะได้รับความสามารถเดียวกันโดยไม่ต้องใช้การลากด้วยภาพ ซึ่งเป็นสิ่งสำคัญต่อการเข้าถึง

ทางเลือกสำรองที่รองรับการสัมผัส

สำหรับอุปกรณ์เคลื่อนที่ ให้แทนที่การลากแบบดั้งเดิมด้วย Pointer Events โดยจับแถวไว้เมื่อกดตัวชี้ แปลงตำแหน่งด้วย CSS transform เมื่อขยับตัวชี้ และตรวจหาตำแหน่งของแถวที่อยู่ด้านล่างแล้วจัดลำดับใหม่เมื่อปล่อยตัวชี้ ไลบรารีอย่าง SortableJS จะห่อหุ้มรูปแบบนี้ให้ใช้ได้กับรูปแบบอินพุตต่าง ๆ

ตรวจสอบความรู้

เหตุใดเราจึงคำนวณตำแหน่งแทรกจากตำแหน่งของเคอร์เซอร์เทียบกับจุดกึ่งกลางแนวตั้งของแถวที่เคอร์เซอร์วางอยู่

สรุป

รายการจัดลำดับใหม่ที่มีความทนทานประกอบด้วย draggable="true" + การเริ่มลาก (บันทึกรหัส, effectAllowed=move) + การลากผ่าน (preventDefault + ตำแหน่งตัวบ่งชี้) + การวาง (insertBefore ณ ตำแหน่งที่ได้จากจุดกึ่งกลาง) + การสิ้นสุดการลาก (ล้างข้อมูล) หลังการวาง ให้หาลำดับใหม่จาก DOM เสมอ และจัดเตรียมทางเลือกด้วยแป้นพิมพ์เพื่อการเข้าถึง

เริ่มต้นได้ฟรี

เรียนรู้ HTML ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
40
บทเรียน
159

คำถามที่พบบ่อย

บทเรียน “รายการลากเพื่อจัดลำดับใหม่ภาคปฏิบัติ” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “รายการลากเพื่อจัดลำดับใหม่ภาคปฏิบัติ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส HTML Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส HTML Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “รายการลากเพื่อจัดลำดับใหม่ภาคปฏิบัติ”

สร้างรายการที่จัดลำดับใหม่ได้ด้วย Drag and Drop API คุณปฏิบัติ HTML Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน HTML Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน HTML Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “รายการลากเพื่อจัดลำดับใหม่ภาคปฏิบัติ” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน HTML Academy นี้ได้ไหม

ได้ บทเรียน HTML Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. แอตทริบิวต์ draggable และเหตุการณ์ dragstart
  2. เหตุการณ์ dragover และ drop
  3. ออบเจ็กต์ dataTransfer
  4. รายการลากเพื่อจัดลำดับใหม่ภาคปฏิบัติ
← กลับไปที่ HTML Academy