❝前期回顾: 1. Page Visibility API 2. Broadcast Channel API 3. Beacon API 4. Resize Observer API 5. Clipboard API 6. Fetch API 7. Performance API 8. WebStorage API 9. WebSockets API 10. Fullscreen API 11. Geolocation API ❞
HTML 拖放 API (Drag and Drop[1])用于在网页中实现拖放功能。通过拖放 API,我们可以实现将可拖拽(draggable)元素拖动到另一个可放置(droppable)元素,以及实现交互式的拖放体验。这个 API 提供了一系列的事件和方法,使我们能够轻松地处理拖放操作。
拖放 API 作用在于使网页具备拖放功能,为用户提供更直观、灵活的交互体验。这里介绍几个常见的使用场景:
拖放 API 的灵活性和易用性使得它成为开发者们构建交互性强大的网页应用程序的理想选择。
使用拖放 API 主要包括以下 3 个步骤:
下面是一个简单的示例代码,演示了如何使用拖放 API :
// 定义可拖拽的元素
const dragSource = document.getElementById("drag-source");
dragSource.addEventListener("dragstart", (event) => {
event.dataTransfer.setData("text/plain", event.target.id);
});
// 定义可放置的元素
const dropTarget = document.getElementById("drop-target");
dropTarget.addEventListener("dragover", (event) => {
event.preventDefault();
});
// 处理放置事件
dropTarget.addEventListener("drop", (event) => {
event.preventDefault();
const data = event.dataTransfer.getData("text/plain");
const draggedElement = document.getElementById(data);
dropTarget.appendChild(draggedElement);
});
在这个示例中,我们通过分别将元素 drag-source
和 drop-target
设置为可拖拽元素和可放置元素,冰分别监听 dragstart
和 dragover
事件,添加相应的处理逻辑,实现了一个简单的拖放操作。当拖动 drag-source
元素时,使用 event.dataTransfer.setData()
方法设置了拖动数据,而放置目标元素时,执行 drop
事件监听的回调方法,实现被拖动的元素添加到可放置元素底下。
拖放 API 在实际应用中有许多用途。下面是一些常见的实际应用场景:
在相册应用中,用户可以拖动图片到不同的分组或标签中进行分类和管理。下面是一个简单的示例代码,演示了如何使用拖放 API 实现图片库的拖放功能:
<style>
.album {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.album img {
width: 150px;
height: 150px;
object-fit: cover;
cursor: move;
}
.highlight {
border-color: #ff0000;
}
</style>
</head>
<body>
<div id="album-1" class="album">
<img id="photo-1" draggable="true" alt="Photo 1"
src="https://th.bing.com/th/id/OIG.m8Fs4GYEDFhEHVFLHPSv?pid=ImgGn"
/>
<img id="photo-2" draggable="true" alt="Photo 2"
src="https://th.bing.com/th/id/OIG.5eGiRmmq0t8jdtIzNjL6?pid=ImgGn"
/>
</div>
<div id="album-2" class="album">
<img id="photo-3" draggable="true" alt="Photo 3"
src="https://th.bing.com/th/id/OIG.D4dUFPI0FNTcK5qlrc3b?pid=ImgGn"
/>
<img id="photo-4" draggable="true" alt="Photo 4"
src="https://th.bing.com/th/id/OIG.oJmwyH4Eobphjk0qtZxz?pid=ImgGn"
/>
</div>
<script>
const albums = document.querySelectorAll(".album");
albums.forEach((album) => {
album.addEventListener("dragstart", (event) => {
event.dataTransfer.setData("text/plain", event.target.id);
event.target.classList.add("highlight");
});
album.addEventListener("dragend", (event) => {
event.target.classList.remove("highlight");
});
album.addEventListener("dragover", (event) => {
event.preventDefault();
album.classList.add("highlight");
});
album.addEventListener("dragleave", () => {
album.classList.remove("highlight");
});
album.addEventListener("drop", (event) => {
event.preventDefault();
album.classList.remove("highlight");
const photoId = event.dataTransfer.getData("text/plain");
const photo = document.getElementById(photoId);
const clonedPhoto = photo.cloneNode(true);
album.appendChild(clonedPhoto);
});
});
</script>
在这个示例中,我们创建了两个相册容器(「album-1」和「album-2」),每个相册容器中包含了一些可拖动的图片元素。当拖动图片时,我们使用 dragstart
事件将图片的 ID 存储在 dataTransfer
对象中。在放置目标容器上,我们使用 dragover
事件阻止默认行为并添加一些过渡样式,使用 dragleave
事件移除过渡样式,使用 drop
事件在放置目标容器中追加拖动的图片元素。通过这样的实现,用户可以轻松地将图片拖动到不同的相册中进行分类和管理。
在项目任务管理应用中,用户可以通过拖动任务卡片进行排序、分组或更改任务状态。下面是一个简单的示例代码,演示了如何使用拖放 API 实现项目任务管理应用中的拖放功能:
<div id="task-list">
<div class="task" draggable="true">任务 1</div>
<div class="task" draggable="true">任务 2</div>
<div class="task" draggable="true">任务 3</div>
</div>
<script>
// 定义拖动源
const draggableTasks = document.querySelectorAll(".task");
draggableTasks.forEach((task) => {
task.addEventListener("dragstart", (event) => {
event.dataTransfer.setData("text/plain", event.target.innerText);
});
});
// 定义放置目标
const taskList = document.getElementById("task-list");
taskList.addEventListener("dragover", (event) => {
event.preventDefault();
taskList.classList.add("highlight");
});
taskList.addEventListener("dragleave", () => {
taskList.classList.remove("highlight");
});
taskList.addEventListener("drop", (event) => {
event.preventDefault();
taskList.classList.remove("highlight");
const taskName = event.dataTransfer.getData("text/plain");
const task = document.createElement("div");
task.innerText = taskName;
task.classList.add("task");
taskList.appendChild(task);
});
</script>
在上述示例中,我们创建了一个任务列表容器(task-list
),其中包含了几个可拖动的任务卡片。当拖动任务卡片时:
dragstart
事件将任务名称存储在 dataTransfer
对象中;dragover
事件阻止默认行为并添加视觉反馈;dragleave
事件移除视觉反馈;drop
事件在任务列表容器中创建新的任务卡片。通过这样的实现,用户可以通过拖动任务卡片来进行排序、分组或更改任务状态。
拖放 API 在页面生成器应用程序中也有广泛的应用,尤其是海报设计器、低代码平台等。页面生成器允许用户通过拖放组件来创建自定义的网页布局和内容。下面是一个完整示例代码,演示了如何使用拖放 API 实现页面生成器中的拖放功能:
<style>
#canvas {
border: 2px dashed #ccc;
padding: 10px;
min-height: 200px;
margin-bottom: 20px;
}
.component {
background-color: #f0f0f0;
padding: 10px;
margin-bottom: 10px;
cursor: move;
}
#page {
border: 2px solid #ccc;
padding: 20px;
min-height: 200px;
}
.highlight {
border-color: #ff0000;
}
</style>
<div id="canvas">
<div class="component" draggable="true">文本组件</div>
<div class="component" draggable="true">图片组件</div>
<div class="component" draggable="true">按钮组件</div>
</div>
<div id="page">
<h1>我的页面</h1>
</div>
<script>
// 定义拖动源
const draggableComponents = document.querySelectorAll(".component");
draggableComponents.forEach((component) => {
component.addEventListener("dragstart", (event) => {
event.dataTransfer.setData("text/plain", event.target.innerText);
});
});
// 定义放置目标
const page = document.getElementById("page");
page.addEventListener("dragover", (event) => {
event.preventDefault();
page.classList.add("highlight");
});
page.addEventListener("dragleave", () => {
page.classList.remove("highlight");
});
page.addEventListener("drop", (event) => {
event.preventDefault();
page.classList.remove("highlight");
const componentName = event.dataTransfer.getData("text/plain");
const component = document.createElement("div");
component.innerText = componentName;
component.classList.add("component");
page.appendChild(component);
});
</script>
以下是 Channel Messaging API 的兼容性列表,包含了主流浏览器及其支持的最低版本:
也可以在 caniuse.com[6] 上查看具体的兼容性信息。
拖放 API 有以下优点和缺点:优点:
缺点:
以下是 5 个推荐的工具,可辅助您在使用拖放 API 进行开发时提高效率:
通过使用这些工具,您可以简化拖放操作的实现,并提高开发效率。
以下是一些建议和注意事项:
遵循这些建议和注意事项,可以更好地应用拖放 API ,并为用户提供优秀的拖放体验。
本文主要介绍了 Drag and Drop API,我们了解了这个 API 的作用和如何使用,在文章中还通过一些常见使用示例和大家展示代码如何实现,最后还给出一些使用建议和注意,希望大家能够更好的了解 Drag and Drop API,在实际工作中能够合理使用。
以下是一些拓展阅读资源,可以帮助您深入学习和理解拖放 API :
阅读这些资源将帮助大家更深入地了解拖放 API 的更多细节和最佳实践。
[1]
Drag and Drop: https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API
[2]
dragstart: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragstart_event
[3]
drag: https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/drag_event
[4]
dragend: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragend_event
[5]
drop: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/drop_event
[6]
caniuse.com: https://caniuse.com/?search=Drag%20and%20Drop
[7]
Sortable: https://github.com/SortableJS/Sortable
[8]
dragula: https://github.com/bevacqua/dragula
[9]
React DnD: https://github.com/react-dnd/react-dnd
[10]
Vue.Draggable: https://github.com/SortableJS/Vue.Draggable
[11]
MDN Web - HTML Drag and Drop API: https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API
[12]
HTML5 Rocks - Native HTML5 Drag and Drop: http://www.html5rocks.com/en/tutorials/dnd/basics/
[13]
A List Apart - Beyond Drag and Drop: https://alistapart.com/article/beyonddraganddrop/
往期回顾
#
如何使用 TypeScript 开发 React 函数式组件?
#
#
#
#
6 个你必须明白 Vue3 的 ref 和 reactive 问题
#
#