js拖拽模板实现方式
原生JavaScript实现拖拽
使用原生JavaScript可以通过监听鼠标事件实现拖拽功能。以下是一个基础实现模板:
const draggableElement = document.getElementById('draggable');
let isDragging = false;
let offsetX, offsetY;
draggableElement.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - draggableElement.getBoundingClientRect().left;
offsetY = e.clientY - draggableElement.getBoundingClientRect().top;
draggableElement.style.cursor = 'grabbing';
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
const x = e.clientX - offsetX;
const y = e.clientY - offsetY;
draggableElement.style.left = `${x}px`;
draggableElement.style.top = `${y}px`;
});
document.addEventListener('mouseup', () => {
isDragging = false;
draggableElement.style.cursor = 'grab';
});
需要确保拖拽元素具有CSS定位属性:
#draggable {
position: absolute;
cursor: grab;
user-select: none;
}
HTML5拖放API实现
HTML5提供了原生拖放API,适合更复杂的拖拽场景:
const draggable = document.getElementById('draggable');
draggable.setAttribute('draggable', 'true');
draggable.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', draggable.id);
e.dataTransfer.effectAllowed = 'move';
});
const dropZone = document.getElementById('dropzone');
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
const id = e.dataTransfer.getData('text/plain');
const draggedElement = document.getElementById(id);
dropZone.appendChild(draggedElement);
});
React实现拖拽组件
在React中可以使用react-dnd库或自定义hooks实现:
import { useRef, useState } from 'react';
function Draggable({ children }) {
const [position, setPosition] = useState({ x: 0, y: 0 });
const [isDragging, setIsDragging] = useState(false);
const ref = useRef(null);
const handleMouseDown = (e) => {
setIsDragging(true);
const rect = ref.current.getBoundingClientRect();
const offsetX = e.clientX - rect.left;
const offsetY = e.clientY - rect.top;
const handleMouseMove = (e) => {
setPosition({
x: e.clientX - offsetX,
y: e.clientY - offsetY
});
};
const handleMouseUp = () => {
setIsDragging(false);
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
};
return (
<div
ref={ref}
style={{
position: 'absolute',
left: position.x,
top: position.y,
cursor: isDragging ? 'grabbing' : 'grab'
}}
onMouseDown={handleMouseDown}
>
{children}
</div>
);
}
Vue实现拖拽指令
Vue中可以创建自定义指令实现拖拽功能:
Vue.directive('drag', {
bind(el, binding) {
let isDragging = false;
let offsetX, offsetY;
el.style.position = 'absolute';
el.style.cursor = 'grab';
el.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - el.getBoundingClientRect().left;
offsetY = e.clientY - el.getBoundingClientRect().top;
el.style.cursor = 'grabbing';
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
const x = e.clientX - offsetX;
const y = e.clientY - offsetY;
el.style.left = `${x}px`;
el.style.top = `${y}px`;
});
document.addEventListener('mouseup', () => {
isDragging = false;
el.style.cursor = 'grab';
});
}
});
使用方式:
<div v-drag>可拖拽元素</div>
拖拽限制边界
为拖拽添加边界限制,防止元素被拖出可视区域:
function constrainPosition(element, x, y) {
const rect = element.getBoundingClientRect();
const maxX = window.innerWidth - rect.width;
const maxY = window.innerHeight - rect.height;
return {
x: Math.max(0, Math.min(x, maxX)),
y: Math.max(0, Math.min(y, maxY))
};
}
// 在mousemove事件中使用
const constrained = constrainPosition(draggableElement, x, y);
draggableElement.style.left = `${constrained.x}px`;
draggableElement.style.top = `${constrained.y}px`;






