vue快速实现拖拽指令
基础拖拽指令实现
通过v-drag指令实现元素拖拽功能,核心是利用鼠标事件和CSS变换:
Vue.directive('drag', {
inserted(el) {
el.style.cursor = 'move';
let startX = 0, startY = 0;
el.addEventListener('mousedown', (e) => {
startX = e.clientX - el.getBoundingClientRect().left;
startY = e.clientY - el.getBoundingClientRect().top;
document.addEventListener('mousemove', move);
document.addEventListener('mouseup', up);
});
function move(e) {
el.style.left = e.clientX - startX + 'px';
el.style.top = e.clientY - startY + 'px';
}
function up() {
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', up);
}
}
})
使用前确保目标元素有position: absolute样式:
<div v-drag style="position:absolute">可拖拽元素</div>
带边界限制的拖拽
增加边界检测逻辑防止元素被拖出可视区域:
function move(e) {
const maxX = window.innerWidth - el.offsetWidth;
const maxY = window.innerHeight - el.offsetHeight;
let x = e.clientX - startX;
let y = e.clientY - startY;
x = Math.max(0, Math.min(x, maxX));
y = Math.max(0, Math.min(y, maxY));
el.style.left = x + 'px';
el.style.top = y + 'px';
}
拖拽手柄实现
仅允许特定区域触发拖拽:
Vue.directive('drag', {
inserted(el, binding) {
const handle = binding.value
? el.querySelector(binding.value)
: el;
handle.style.cursor = 'move';
// 其余逻辑与基础实现相同
}
})
使用时指定手柄选择器:
<div v-drag="'.handle'">
<div class="handle">拖拽区</div>
<div>内容区</div>
</div>
拖拽数据绑定
通过指令参数传递拖拽位置数据:
function move(e) {
// ...计算x,y...
if (binding.arg) {
Vue.set(binding.value, binding.arg, {x, y});
}
}
组件内使用方式:
data() {
return { pos: {x:0, y:0} }
}
<div v-drag:pos="pos" :style="{left:pos.x+'px',top:pos.y+'px'}"></div>
触摸屏适配
添加触摸事件支持:
el.addEventListener('touchstart', (e) => {
const touch = e.touches[0];
startX = touch.clientX - el.getBoundingClientRect().left;
// 其余逻辑类似mousedown
});
document.addEventListener('touchmove', touchMove);
document.addEventListener('touchend', up);
性能优化建议
使用CSS transform替代top/left减少重排:
el.style.transform = `translate(${x}px, ${y}px)`;
添加防抖处理高频mousemove事件:
function move(e) {
requestAnimationFrame(() => {
// 位置计算逻辑
});
}






