html和css代码如下
<style>
.item {
width: 200px;
height: 50px;
background: rgb(15, 226, 219);
margin: 10px 0;
padding-left: 20px;
border-radius: 10px;
line-height: 50px;
}
.item.move {
background: transparent;
color: transparent;
border: 1px dashed #ccc;
}
</style>
</head>
<body>
<div class="list">
<div draggable="true" class="item">1</div>
<div draggable="true" class="item">2</div>
<div draggable="true" class="item">3</div>
<div draggable="true" class="item">4</div>
<div draggable="true" class="item">5</div>
<div draggable="true" class="item">6</div>
<div draggable="true" class="item">7</div>
<div draggable="true" class="item">8</div>
</div>
这是每一个序列,定义好样式后,通过监听dragstart事件,开始拖动事件,给他加上拖拽后的虚线样式,也就是这样
但此时,拖住的元素也是虚线的,因为拖住的时候,原始的元素就改变了,拖住的元素的样式是根据原来的样式来决定的,所以我们可以放入一个异步里,也就是setTimeout中(用了事件委托)
但为啥原来的位置也变成异步了?????
// 利用了事件委托
list.addEventListener("dragstart", function (e) {
// 使用setTimeout让他拖拽的元素不要变成虚线,还是原来的样式,放入一个异步任务里就行
setTimeout(() => {
e.target.classList.add('move')
}, 0)
sourceDiv = e.target
e.dataTransfer.effectAllowed = 'move'
})
e.dataTransfer.effectAllowed = 'move'是设置鼠标样式为move的样式
如果拖进的元素是父容器或者他自身则不拖进
if (e.target == list || e.target == sourceDiv) {
return
}
通过扩展运算符,将伪数组转换为数组
const children = [...list.children]
这样就可以通过indexOf获取对应元素的索引,比如拖住的元素的索引,和进入元素的索引
我们通过判断是上移还是下移来决定元素的排序,如果是上移,那么拖住的元素要插入进入的元素之前,如果是下移,那么拖住的元素要插入拖入元素的下一个同类元素的前面,这是上移和下移的区别
// 上移
if (sourceIndex > targetIndex) {
list.insertBefore(sourceDiv, e.target)
} else {
// 下移
list.insertBefore(sourceDiv, e.target.nextElementSibling)
}
})
拖拽结束后要把之前添加的move类,也就是虚线透明样式给删除
// 拖拽结束后,最后将虚线方框移除
list.addEventListener("dragend", function (e) {
e.target.classList.remove('move')
})
还有dragenter和dragover事件的默认行为是拒绝接受任何被拖放的元素。因此,我们必须阻止浏览器这种默认行为。
这样就完成了拖拽序列
全部代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.item {
width: 200px;
height: 50px;
background: rgb(15, 226, 219);
margin: 10px 0;
padding-left: 20px;
border-radius: 10px;
line-height: 50px;
}
.item.move {
background: transparent;
color: transparent;
border: 1px dashed #ccc;
}
</style>
</head>
<body>
<div class="list">
<div draggable="true" class="item">1</div>
<div draggable="true" class="item">2</div>
<div draggable="true" class="item">3</div>
<div draggable="true" class="item">4</div>
<div draggable="true" class="item">5</div>
<div draggable="true" class="item">6</div>
<div draggable="true" class="item">7</div>
<div draggable="true" class="item">8</div>
</div>
<script>
const list = document.querySelector('.list')
let sourceDiv
// 利用了事件委托
list.addEventListener("dragstart", function (e) {
// 使用setTimeout让他拖拽的元素不要变成虚线,还是原来的样式,放入一个异步任务里就行
setTimeout(() => {
e.target.classList.add('move')
}, 0)
sourceDiv = e.target
e.dataTransfer.effectAllowed = 'move'
})
// 阻止拖拽的默认行为
list.addEventListener('dragover', function (e) {
e.preventDefault()
})
list.addEventListener("dragenter", function (e) {
//拖动API----- 阻止浏览器默认事件,因为会出现元素回到原始自身上的位置
e.preventDefault()
// 如果拖进的元素是父容器或者他自身则不拖进
if (e.target == list || e.target == sourceDiv) {
return
}
const children = [...list.children]
const sourceIndex = children.indexOf(sourceDiv)
const targetIndex = children.indexOf(e.target)
// 上移
if (sourceIndex > targetIndex) {
list.insertBefore(sourceDiv, e.target)
} else {
// 下移
list.insertBefore(sourceDiv, e.target.nextElementSibling)
}
})
// 拖拽结束后,最后将虚线方框移除
list.addEventListener("dragend", function (e) {
e.target.classList.remove('move')
})
</script>
</body>
</html>