vue指令实现拖拽
Vue 指令实现拖拽功能
在 Vue 中可以通过自定义指令实现拖拽功能,以下是两种常见的方法:
方法一:基础拖拽指令
注册一个全局指令或在组件中定义局部指令:

Vue.directive('drag', {
bind(el, binding) {
el.style.position = 'absolute';
let startX, startY, initialX, initialY;
el.addEventListener('mousedown', (e) => {
startX = e.clientX;
startY = e.clientY;
initialX = el.offsetLeft;
initialY = el.offsetTop;
document.addEventListener('mousemove', moveElement);
document.addEventListener('mouseup', stopDrag);
e.preventDefault();
});
function moveElement(e) {
const dx = e.clientX - startX;
const dy = e.clientY - startY;
el.style.left = `${initialX + dx}px`;
el.style.top = `${initialY + dy}px`;
}
function stopDrag() {
document.removeEventListener('mousemove', moveElement);
document.removeEventListener('mouseup', stopDrag);
}
}
});
使用方式:
<div v-drag style="width: 100px; height: 100px; background: red;"></div>
方法二:支持边界限制的拖拽

Vue.directive('drag', {
bind(el, binding) {
el.style.position = 'absolute';
let startX, startY, initialX, initialY;
const parent = el.parentElement;
el.addEventListener('mousedown', (e) => {
startX = e.clientX;
startY = e.clientY;
initialX = el.offsetLeft;
initialY = el.offsetTop;
document.addEventListener('mousemove', moveElement);
document.addEventListener('mouseup', stopDrag);
e.preventDefault();
});
function moveElement(e) {
const dx = e.clientX - startX;
const dy = e.clientY - startY;
let newX = initialX + dx;
let newY = initialY + dy;
// 边界检查
if (parent) {
newX = Math.max(0, Math.min(newX, parent.clientWidth - el.offsetWidth));
newY = Math.max(0, Math.min(newY, parent.clientHeight - el.offsetHeight));
}
el.style.left = `${newX}px`;
el.style.top = `${newY}px`;
}
function stopDrag() {
document.removeEventListener('mousemove', moveElement);
document.removeEventListener('mouseup', stopDrag);
}
}
});
方法三:支持拖拽数据传递
Vue.directive('drag', {
bind(el, binding) {
el.draggable = true;
el.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', binding.value);
});
}
});
// 在目标元素上使用 @drop 和 @dragover.prevent
注意事项
- 确保拖拽元素设置了
position: absolute或position: relative - 考虑添加
user-select: none防止文本选中干扰拖拽 - 移动端需要添加 touch 事件支持
- 复杂场景建议使用现成的拖拽库如
vue-draggable






