首先是使用h5的api实现拖拽排序效果
需要实现的效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
display: flex;
flex-direction: row;
align-content: center;
justify-content: center;
align-items: center;
}
.list {
/* 去除ul小点 */
list-style: none;
}
.list-item {
user-select: none;
width: 400px;
height: 35px;
line-height: 35px;
text-align: center;
border: 1px solid #ccc;
/* 渐变背景 */
background: linear-gradient(to right, #015d69, #51b9ff);
cursor: move;
color: #fff;
border-radius: 10px;
}
.list-item.moving {
background: transparent;
color: transparent;
border: 1px dashed #ccc;
}
</style>
</head>
<body>
<ul class="list">
<li draggable="true" class="list-item">1</li>
<li draggable="true" class="list-item">2</li>
<li draggable="true" class="list-item">3</li>
<li draggable="true" class="list-item">4</li>
<li draggable="true" class="list-item">5</li>
<li draggable="true" class="list-item">6</li>
<li draggable="true" class="list-item">7</li>
<li draggable="true" class="list-item">8</li>
</ul>
<script>
const list = document.querySelector('.list');
let sourceNode; //当前在拖动的节点
list.ondragstart = e => {
setTimeout(() => {
e.target.classList.add('moving')
}, 0);
sourceNode = e.target
e.dataTransfer.effectAllowed = 'move';
}
list.ondragover = e => {
e.preventDefault()
}
list.ondragenter = e => {
e.preventDefault();
if (e.target === list || e.target === sourceNode) {
return
}
const children = Array.from(list.children)
const sourceIndex = children.indexOf(sourceNode)
const targetIndex = children.indexOf(e.target)
if (sourceIndex < targetIndex) {
list.insertBefore(sourceNode, e.target.nextElementSibling)
} else {
list.insertBefore(sourceNode, e.target)
}
}
list.ondragend = e => {
e.target.classList.remove('moving')
}
</script>
</body>
</html>
原理解析
这是因为使用了h5的 draggable属性,页面中设置了 draggable=“true” 属性的元素可以进行拖拽
示例如下
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
display: flex;
flex-direction: row;
align-content: center;
justify-content: space-evenly;
align-items: center;
}
.box {
width: 200px;
height: 200px;
background-color: red;
line-height: 200px;
text-align: center;
}
</style>
</head>
<body>
<div class="box">未添加draggable</div>
<div draggable="true" class="box">添加了draggable</div>
</body>
</html>
效果示例
给 box1 增加了draggable=“true” 属性之后, box1 就变成可以拖拽的了。但是拖拽之后要做什么事情?就涉及到事件监听。
拖拽元素的事件监听:(应用于拖拽元素)
- ondragstart当拖拽开始时调用
- ondragleave 当鼠标离开拖拽元素时调用
- ondragend 当拖拽结束时调用
- ondrag 整个拖拽过程都会调用
演示一下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
display: flex;
flex-direction: row;
align-content: center;
justify-content: space-evenly;
align-items: center;
}
.box {
width: 200px;
height: 200px;
background-color: red;
line-height: 200px;
text-align: center;
}
</style>
</head>
<body>
<div class="box">未添加draggable</div>
<div id="box" draggable="true" class="box">添加了draggable</div>
<script>
var box = document.querySelector('#box');
// 绑定拖拽事件
// 拖拽开始
box.ondragstart = function () {
console.log('拖拽开始.');
}
// 拖拽离开:鼠标拖拽时离开被拖拽的元素时触发
box.ondragleave = function () {
console.log('拖拽离开..');
}
// 拖拽结束
box.ondragend = function () {
console.log('拖拽结束...');
console.log("---------------");
}
box.ondrag = function () {
console.log('拖拽');
}
</script>
</body>
</html>
效果展示
请忽略那些报错,那是浏览器插件的报错
目标元素
拖动元素侦听完成了,剩下的就是实现如何的把元素放到目标元素那里去了
比如说,你想把元素A拖拽到元素B里,那么元素B就是目标元素。
页面中任何一个元素都可以成为目标元素。
目标元素的事件监听:(应用于目标元素)
- ondragenter 当拖拽元素进入时调用
- ondragover 当拖拽元素停留在目标元素上时,就会连续一直触发(不管拖拽元素此时是移动还是不动的状态)
- ondrop 当在目标元素上松开鼠标时调用
- ondragleave 当鼠标离开目标元素时调用
效果如下
代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
display: flex;
flex-direction: row;
align-content: center;
justify-content: space-evenly;
align-items: center;
}
.box {
width: 200px;
height: 200px;
background-color: red;
line-height: 200px;
text-align: center;
}
.target-box {
width: 500px;
height: 500px;
background-color: green;
line-height: 300px;
text-align: center;
}
</style>
</head>
<body>
<div class="box">未添加draggable</div>
<div id="box" draggable="true" class="box">添加了draggable</div>
<div class="target-box"></div>
<script>
// var box = document.querySelector('#box');
// // 绑定拖拽事件
// // 拖拽开始ondragstart 触发
// box.ondragstart = function () {
// console.log('拖拽开始.');
// }
// // 拖拽离开:鼠标拖拽时离开被拖拽的元素时ondragleave 触发
// box.ondragleave = function () {
// console.log('拖拽离开..');
// }
// // 拖拽结束ondragend 事件触发
// box.ondragend = function () {
// console.log('拖拽结束...');
// console.log("---------------");
// }
// box.ondrag = function () {
// console.log('拖拽');
// }
var two = document.querySelector('.target-box');
//目标元素的拖拽事件
// 当被拖拽元素进入时ondragenter 触发
two.ondragenter = function () {
console.log("移入目标盒子.");
}
// 当被拖拽元素离开时ondragleave 触发
two.ondragleave = function () {
console.log("移出目标盒子");
}
// 当拖拽元素在 目标元素上时,ondragover 会连续触发
two.ondragover = function (e) {
//阻止拖拽事件的默认行为
e.preventDefault();
console.log("在目标盒子上");
}
// 当在目标元素上松开鼠标时ondrop 触发
two.ondrop = function () {
console.log("在目标盒子上松开了鼠标");
}
</script>
</body>
</html>