效果示例图
代码示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
* {
padding: 0px;
margin: 0px;
box-sizing: border-box;
}
.list {
width: 600px;
margin: 100px auto;
}
.list-item {
border: 1px solid #00a2ef;
border-radius: 6px;
width: 100%;
height: 50px;
line-height: 50px;
font-size: 16px;
color: #fff;
text-align: center;
margin-bottom: 6px;
background-color: #00a2ef;
user-select: none;
cursor: move;
}
.list-item.moving {
background: transparent;
border: 1px solid #ccc;
color: #ccc;
}
</style>
</head>
<body>
<div class="list">
<div draggable="true" class="list-item" data-id="1">item 1</div>
<div draggable="true" class="list-item" data-id="2">item 2</div>
<div draggable="true" class="list-item" data-id="3">item 3</div>
<div draggable="true" class="list-item" data-id="4">item 4</div>
<div draggable="true" class="list-item" data-id="5">item 5</div>
<div draggable="true" class="list-item" data-id="6">item 6</div>
<div draggable="true" class="list-item" data-id="7">item 7</div>
</div>
</body>
<script type="text/javascript">
const list = document.querySelector(".list");
//暂存当前拖动元素节点
let rootNode = null;
/**
* 选中一个元素开始拖动的时候
* **/
list.addEventListener("dragstart", (e) => {
console.log("[开始拖拽]", e.target)
setTimeout(() => {
e.target.classList.add("moving")
}, 0)
rootNode = e.target;
e.dataTransfer.effectAllowed = "move"
})
list.addEventListener("dragover", (e) => {
//阻止事件向上传递
e.preventDefault();
})
/**
* 当拖动元素移动到某个元素或者进入到某个元素的时候,触发事件
* **/
list.addEventListener("dragenter", (e) => {
//阻止事件向上传递
e.preventDefault();
//进入的元素去掉父元素和自己本身
if (e.target === list || e.target === rootNode) {
return;
}
console.log("[拖动元素进入某个元素]", e.target)
//拿到父元素的所有子元素并把这些子元素转换成数组
const children = Array.from(list.children);
//获取拖动元素在孩子数组中的下标
const sourceIndex = children.indexOf(rootNode);
//获取进入的目标元素的下标
const targetIndex = children.indexOf(e.target);
if (sourceIndex < targetIndex) {
console.log("[向下拖动]")
// 把拖动的节点放在当前进入节点的下一个节点的前面
list.insertBefore(rootNode, e.target.nextElementSibling);
} else {
console.log("[向上拖动]")
//把拖动的节点放在当前进入节点的前面
list.insertBefore(rootNode, e.target);
}
})
/**
* 拖动结束
* **/
list.addEventListener("dragend", (e) => {
console.log("[拖动结束]", e)
//删除添加的class样式
e.target.classList.remove("moving");
const children = Array.from(list.children);
const endIndex = children.indexOf(e.target);
if (endIndex == 0) {
console.log("[我排在最前面]")
} else {
const curID = e.target.dataset.id;
const preID = children[endIndex - 1].dataset.id;
console.log(`我ID为${curID}应该排在ID为${preID}的后面`)
}
})
</script>
</html>