Saya berjuang BANYAK dengan ini, bahkan setelah membaca semua jawaban ini, dan berpikir saya mungkin berbagi solusi dengan Anda, karena saya pikir itu mungkin salah satu pendekatan yang lebih sederhana, meskipun agak berbeda. Pikiranku hanya menghilangkan dragleavependengar acara sepenuhnya, dan mengkode perilaku dragleave dengan setiap acara dragenter baru dipecat, sambil memastikan bahwa acara dragenter tidak akan dipecat secara tidak perlu.
Dalam contoh saya di bawah ini, saya memiliki tabel, di mana saya ingin dapat bertukar konten baris tabel satu sama lain melalui drag & drop API. Pada dragenter, kelas CSS akan ditambahkan ke elemen baris di mana Anda saat ini menyeret elemen Anda, untuk menyorotnya, dan pada dragleave, kelas ini akan dihapus.
Contoh:
Tabel HTML yang sangat mendasar:
<table>
<tr>
<td draggable="true" class="table-cell">Hello</td>
</tr>
<tr>
<td draggable="true" clas="table-cell">There</td>
</tr>
</table>
Dan fungsi dragenter event handler, ditambahkan ke setiap sel tabel (samping dragstart, dragover, drop, dan dragendpenangan, yang tidak spesifik untuk pertanyaan ini, sehingga tidak disalin di sini):
/*##############################################################################
## Dragenter Handler ##
##############################################################################*/
// When dragging over the text node of a table cell (the text in a table cell),
// while previously being over the table cell element, the dragleave event gets
// fired, which stops the highlighting of the currently dragged cell. To avoid
// this problem and any coding around to fight it, everything has been
// programmed with the dragenter event handler only; no more dragleave needed
// For the dragenter event, e.target corresponds to the element into which the
// drag enters. This fact has been used to program the code as follows:
var previousRow = null;
function handleDragEnter(e) {
// Assure that dragenter code is only executed when entering an element (and
// for example not when entering a text node)
if (e.target.nodeType === 1) {
// Get the currently entered row
let currentRow = this.closest('tr');
// Check if the currently entered row is different from the row entered via
// the last drag
if (previousRow !== null) {
if (currentRow !== previousRow) {
// If so, remove the class responsible for highlighting it via CSS from
// it
previousRow.className = "";
}
}
// Each time an HTML element is entered, add the class responsible for
// highlighting it via CSS onto its containing row (or onto itself, if row)
currentRow.className = "ready-for-drop";
// To know which row has been the last one entered when this function will
// be called again, assign the previousRow variable of the global scope onto
// the currentRow from this function run
previousRow = currentRow;
}
}
Komentar yang sangat mendasar ditinggalkan dalam kode, sehingga kode ini cocok untuk pemula juga. Semoga ini bisa membantu Anda! Perhatikan bahwa Anda tentu saja perlu menambahkan semua pendengar acara yang saya sebutkan di atas ke setiap sel tabel agar ini berfungsi.