js拖拽模板实现方式
原生 JavaScript 实现拖拽
监听目标元素的 mousedown 事件,记录初始位置。在 mousemove 事件中计算偏移量并更新元素位置。mouseup 事件中移除移动监听。
const draggable = document.getElementById('draggable');
let offsetX, offsetY;
draggable.addEventListener('mousedown', (e) => {
offsetX = e.clientX - draggable.getBoundingClientRect().left;
offsetY = e.clientY - draggable.getBoundingClientRect().top;
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
function onMouseMove(e) {
draggable.style.left = `${e.clientX - offsetX}px`;
draggable.style.top = `${e.clientY - offsetY}px`;
}
function onMouseUp() {
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}
HTML5 Drag and Drop API
使用原生拖放接口,需要设置 draggable="true" 并实现相关事件处理器。适用于跨元素拖放场景。

const dragItem = document.getElementById('dragItem');
const dropZone = document.getElementById('dropZone');
dragItem.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', dragItem.id);
});
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
const id = e.dataTransfer.getData('text/plain');
dropZone.appendChild(document.getElementById(id));
});
React 实现拖拽组件
使用 React 的 useState 和事件处理实现组件级拖拽。注意使用 transform 代替直接修改定位属性以获得更好性能。

import { useState } from 'react';
function Draggable({ children }) {
const [position, setPosition] = useState({ x: 0, y: 0 });
const [dragging, setDragging] = useState(false);
const [relPosition, setRelPosition] = useState({ x: 0, y: 0 });
const onMouseDown = (e) => {
const rect = e.currentTarget.getBoundingClientRect();
setRelPosition({
x: e.clientX - rect.left,
y: e.clientY - rect.top
});
setDragging(true);
};
const onMouseMove = (e) => {
if (!dragging) return;
setPosition({
x: e.clientX - relPosition.x,
y: e.clientY - relPosition.y
});
};
const onMouseUp = () => {
setDragging(false);
};
return (
<div
style={{
transform: `translate(${position.x}px, ${position.y}px)`,
cursor: dragging ? 'grabbing' : 'grab'
}}
onMouseDown={onMouseDown}
onMouseMove={onMouseMove}
onMouseUp={onMouseUp}
onMouseLeave={onMouseUp}
>
{children}
</div>
);
}
Vue 拖拽指令实现
通过自定义指令封装拖拽逻辑,实现可复用拖拽功能。利用 Vue 的指令生命周期钩子处理拖拽状态。
Vue.directive('drag', {
bind(el, binding) {
let startX, startY, initialX, initialY;
el.style.position = binding.value?.position || 'absolute';
el.addEventListener('mousedown', (e) => {
startX = e.clientX;
startY = e.clientY;
initialX = el.offsetLeft;
initialY = el.offsetTop;
document.addEventListener('mousemove', move);
document.addEventListener('mouseup', stop);
e.preventDefault();
});
function move(e) {
el.style.left = `${initialX + e.clientX - startX}px`;
el.style.top = `${initialY + e.clientY - startY}px`;
}
function stop() {
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', stop);
}
}
});
第三方库解决方案
使用流行拖拽库如 interact.js 或 Draggable.js 可快速实现复杂交互。以下为 interact.js 示例:
interact('.draggable').draggable({
inertia: true,
modifiers: [
interact.modifiers.restrictRect({
restriction: 'parent',
endOnly: true
})
],
listeners: {
move(event) {
const target = event.target;
const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.style.transform = `translate(${x}px, ${y}px)`;
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
}
});






