从零实现一个原生js拖拽排序功能
源码如下:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title></title>
<style>
#root {
position: relative;
width: 500px;
margin: 100px auto;
border: 1px solid red;
}
.item {
width: 100%;
position: absolute;
left: 0;
background-color: rgba(15, 128, 255, 0.4);
border-bottom: 1px solid blue;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="text/javascript">
// 参数
const data = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
const height = 50
// 初始化变量
let children = []
let target = null
let moveTop = 0
let targetNum = 0
// 渲染元素
const root = document.querySelector('#root')
root.style.height = data.length * height + 'px'
for (let i = 0, len = data.length; i < len; i++) {
const item = data[i]
const div = document.createElement('div')
div.className = 'item'
div.innerText = item
div.style.top = i * height + 'px'
div.style.height = height + 'px'
drag(div)
children.push(div)
root.appendChild(div)
}
// 拖拽
function drag(div) {
div.onmousedown = function(e) {
const top = e.clientY - div.offsetTop
target = div
targetNum = Math.round(div.offsetTop / height)
document.onmousemove = function(e) {
moveTop = e.clientY - top
target.style.top = moveTop + 'px'
move()
}
}
}
// 鼠标松开设置最终落下位置
document.onmouseup = function() {
document.onmousemove = null
if (!target) return null
const nowNum = Math.round(moveTop / height)
if (nowNum >= children.length - 1) {
target.style.top = (children.length - 1) * height + 'px'
} else if (nowNum <= 0) {
target.style.top = '0px'
} else {
target.style.top = nowNum * height + 'px'
}
}
// 交换位置
function move() {
const nowNum = Math.round(moveTop / height)
for (let i = 0, len = children.length; i < len; i++) {
const item = children[i]
if (target === item) {
continue
}
const itemNum = parseInt(item.style.top) / height
if (itemNum === nowNum) {
if (itemNum < targetNum) {
item.style.top = parseInt(item.style.top) + height + 'px'
} else if (itemNum > targetNum) {
item.style.top = parseInt(item.style.top) - height + 'px'
}
targetNum = Math.round(moveTop / height)
return null
}
}
}
</script>
</body>
</html>