你好呀,我是爱编程的Sherry,很高兴在这里遇见你!我是一名拥有十多年开发经验的前端工程师。这一路走来,面对困难时也曾感到迷茫,凭借不懈的努力和坚持,重新找到了前进的方向。我的人生格言是——认准方向,坚持不懈,你终将迎来辉煌!欢迎关注我,我将在这里分享工作中积累的经验和心得,希望我的分享能够给你带来帮助。
有这么一个需求,产品要求实现一个列表拖拽排序功能,鼠标点击元素,按住移动,可将元素拖走,松开移动到新的位置,以完成拖拽排序。
点击“新增项”按钮,向列表中添加新的可拖拽的 li 项。
每个 li 项都有一个删除按钮,点击删除按钮可移除该项。
可以按住列表项拖动,松手时调整顺序。
通过 draggable=“true” 启用列表项的拖拽功能。
dragstart 和 dragend 事件用于处理拖动过程中视觉反馈的变化。
dragover 事件用于实时检测鼠标位置并决定插入的位置。
新增和删除功能通过 DOM 操作动态处理列表项的变化。
这样就能实现一个具备基本排序、新增、删除功能的拖拽列表。
<h2>拖拽排序列表h2>
<button id="addItem">新增项button>
<ul id="sortableList">
<li draggable="true">Item 1 <button class="deleteBtn">删除button>li>
<li draggable="true">Item 2 <button class="deleteBtn">删除button>li>
<li draggable="true">Item 3 <button class="deleteBtn">删除button>li>
ul>
/* 简化并增强样式 */
ul {
list-style-type: none;
padding: 0;
}
li {
margin: 10px;
padding: 15px;
background-color: #f0f0f0;
border: 1px solid #ccc;
cursor: grab;
display: flex;
justify-content: space-between;
}
li.dragging {
opacity: 0.5;
background-color: #c0c0c0;
}
button.deleteBtn {
background-color: red;
color: white;
border: none;
cursor: pointer;
}
button.deleteBtn:hover {
background-color: darkred;
}
const sortableList = document.getElementById("sortableList");
const addItemBtn = document.getElementById("addItem");
addItemBtn.addEventListener("click", () => {
const newItem = document.createElement("li");
newItem.setAttribute("draggable", "true");
newItem.innerHTML = `Item ${sortableList.children.length + 1} `;
sortableList.appendChild(newItem);
addDragAndDeleteListeners(newItem);
});
function addDragAndDeleteListeners(item) {
item.addEventListener("dragstart", () => {
item.classList.add("dragging");
});
item.addEventListener("dragend", () => {
item.classList.remove("dragging");
});
const deleteBtn = item.querySelector(".deleteBtn");
deleteBtn.addEventListener("click", () => {
item.remove();
});
}
sortableList.addEventListener("dragover", (e) => {
e.preventDefault();
const draggingItem = document.querySelector(".dragging");
const closestItem = getDragAfterElement(sortableList, e.clientY);
if (closestItem === null) {
sortableList.appendChild(draggingItem);
} else {
sortableList.insertBefore(draggingItem, closestItem);
}
});
function getDragAfterElement(container, y) {
const listItems = [...container.querySelectorAll("li:not(.dragging)")];
return listItems.reduce((closest, child) => {
const box = child.getBoundingClientRect();
const offset = y - box.top - box.height / 2;
if (offset < 0 && offset > closest.offset) {
return { offset: offset, element: child };
} else {
return closest;
}
}, { offset: Number.NEGATIVE_INFINITY }).element;
}
document.querySelectorAll("#sortableList li").forEach(addDragAndDeleteListeners);
通过上述代码实现了拖拽排序功能的核心特性,首先html创建布局,然后css设计样式,确保良好的视觉反馈,增强用户体验;最后利用html5的draggable属性和相关事件(如dragstart、dragover和dragend)实现元素的拖拽功能。
看十遍不然练一遍,快快动手练起来吧!