Drag & Drop 与 File API
约 647 字大约 2 分钟
布欧-Lewyon
2026-05-16
首页 › HTML › HTML5 API › Drag & Drop 与 File API
Drag & Drop
HTML5 提供了原生拖拽能力,无需第三方库。
拖拽元素
设置 draggable="true" 使元素可拖拽:
<div draggable="true" id="drag1" ondragstart="onDragStart(event)">
拖我
</div>
<div id="dropZone" ondrop="onDrop(event)" ondragover="onDragOver(event)">
放到这里
</div>
<script>
function onDragStart(event) {
event.dataTransfer.setData('text/plain', event.target.id);
event.dataTransfer.effectAllowed = 'move';
}
function onDragOver(event) {
event.preventDefault(); // 必须阻止默认行为才能 drop
event.dataTransfer.dropEffect = 'move';
}
function onDrop(event) {
event.preventDefault();
const id = event.dataTransfer.getData('text/plain');
const draggable = document.getElementById(id);
event.target.appendChild(draggable);
}
</script>事件列表
| 事件 | 触发时机 | 目标 |
|---|---|---|
dragstart | 开始拖拽 | 被拖元素 |
drag | 拖拽中(持续触发) | 被拖元素 |
dragend | 拖拽结束 | 被拖元素 |
dragenter | 进入放置区 | 放置区元素 |
dragover | 在放置区移动 | 放置区元素 |
dragleave | 离开放置区 | 放置区元素 |
drop | 放下 | 放置区元素 |
dataTransfer
dataTransfer 对象在拖拽事件间传递数据:
// 设置
event.dataTransfer.setData('text/plain', '文本数据');
event.dataTransfer.setData('text/html', '<b>HTML</b>');
event.dataTransfer.setData('application/json', JSON.stringify(obj));
// 读取
const text = event.dataTransfer.getData('text/plain');
// 设置拖拽效果(光标形状)
event.dataTransfer.effectAllowed = 'copy'; // 或 'move' / 'link' / 'none'
event.dataTransfer.dropEffect = 'copy'; // 需匹配 effectAllowedFile API
在浏览器中读取用户选择的文件内容(无需上传到服务器)。
选择文件
<input type="file" id="fileInput" multiple accept="image/*,.pdf">
<div id="preview"></div>
<script>
document.getElementById('fileInput').addEventListener('change', (event) => {
const files = event.target.files;
for (const file of files) {
console.log('文件名:', file.name);
console.log('大小:', file.size, 'bytes');
console.log('类型:', file.type);
console.log('上次修改:', new Date(file.lastModified));
}
});
</script>读取文件内容
<!-- 读取图片预览 -->
<script>
document.getElementById('fileInput').addEventListener('change', (event) => {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
const img = document.createElement('img');
img.src = e.target.result; // data: URL
img.style.maxWidth = '200px';
document.getElementById('preview').appendChild(img);
};
reader.onerror = () => {
console.error('文件读取失败');
};
reader.readAsDataURL(file); // 读取为 data URL
});
</script>FileReader 读取方式
| 方法 | 结果 | 场景 |
|---|---|---|
readAsDataURL(file) | data: URL(base64) | 图片/音视频预览 |
readAsText(file, encoding) | 字符串 | 读取文本文件 |
readAsArrayBuffer(file) | ArrayBuffer(二进制) | 文件上传、二进制处理 |
readAsBinaryString(file) | 字符串(已弃用) | 不推荐 |
拖拽上传
<div id="dropArea" style="border: 2px dashed #1890ff; padding: 40px; text-align: center;">
将文件拖拽到此处
</div>
<div id="fileList"></div>
<script>
const dropArea = document.getElementById('dropArea');
dropArea.addEventListener('dragover', (e) => {
e.preventDefault();
dropArea.style.borderColor = '#52c41a';
});
dropArea.addEventListener('dragleave', () => {
dropArea.style.borderColor = '#1890ff';
});
dropArea.addEventListener('drop', (e) => {
e.preventDefault();
dropArea.style.borderColor = '#1890ff';
const files = e.dataTransfer.files;
const list = document.getElementById('fileList');
list.innerHTML = '';
for (const file of files) {
const p = document.createElement('p');
p.textContent = `${file.name} (${(file.size / 1024).toFixed(1)} KB)`;
list.appendChild(p);
}
});
</script>小结
| 功能 | API | 关键事件/方法 |
|---|---|---|
| 拖拽 | Drag & Drop | dragstart / dragover / drop |
| 数据传输 | dataTransfer | setData() / getData() |
| 文件选择 | <input type="file"> | files 属性 |
| 文件读取 | FileReader | readAsDataURL() / readAsText() |
| 拖拽上传 | Drag & Drop + File | e.dataTransfer.files |
