左右选项卡鼠标拖拽交互还是挺常见的,我在练习还原腾讯网时遇到过,还是挺容易的。
Vue3可以使用 vuedraggable@next拖拽组件,他是一个是一个专门为 Vue.js 3 开发的拖拽组件,既然是组件就需要安装依赖咯 :
npm install vuedraggable@next sortablejs
以下为拖拽组件示例代码:
<script setup>
import { ref } from 'vue';
import draggable from 'vuedraggable';
const horizontalTabs = ref([
{ id: 1, name: '选项卡1' },
{ id: 2, name: '选项卡2' },
{ id: 3, name: '选项卡3' },
{ id: 4, name: '选项卡4' }
]);
const verticalTabs = ref([
{ id: 1, name: '选项卡1' },
{ id: 2, name: '选项卡2' },
{ id: 3, name: '选项卡3' },
{ id: 4, name: '选项卡4' }
]);
</script>
<template>
<div class="tab-wrapper">
<h3>左右拖拽</h3>
<draggable v-model="horizontalTabs" item-key="id" direction="horizontal" class="tab-container">
<template #item="{ element }">
<div class="tab">{{ element.name }}</div>
</template>
</draggable>
<h3>上下拖拽</h3>
<draggable v-model="verticalTabs" item-key="id" direction="vertical" class="tab-container vertical">
<template #item="{ element }">
<div class="tab">{{ element.name }}</div>
</template>
</draggable>
</div>
</template>
<style scoped>
.tab-wrapper { padding: 20px; }
.tab-container { display: flex; gap: 10px; padding: 10px; background: #f0f0f0; width: fit-content; margin-bottom: 20px; }
.tab-container.vertical { flex-direction: column; width: 200px; }
.tab { padding: 10px 20px; background: #fff; border: 1px solid #ddd; cursor: grab; user-select: none; }
.tab:active { cursor: grabbing; }
</style>
由此可见使用第三方组件实现拖拽功能非常简单,自行修改样式和选项卡数组即可使用,记得import引入拖拽组件哦。
原生JS写也不难,主要是在于监听鼠标事件、计算位移、调整 DOM 结构,拖拽开始、拖拽中、拖拽结束分别用原生js的
mousedown ,mousemove ,mouseup即可以下提供一个示例代码:
<!DOCTYPE html>
<body>
<div class="tabs" id="tabs">
<div class="tab">1</div>
<div class="tab">2</div>
<div class="tab">3</div>
</div>
<style>
.tabs { display: flex; gap: 10px; padding: 10px; background: #f0f0f0; }
.tab { padding: 10px 20px; background: #fff; border: 1px solid #ddd; cursor: grab; user-select: none; }
.tab:active { cursor: grabbing; }
</style>
<script>
const tabs = document.querySelectorAll('.tab');
let dragTab = null, startX = 0, currentX = 0;
tabs.forEach(tab => {
tab.onmousedown = (e) => {
dragTab = tab;
startX = e.clientX - currentX;
document.onmousemove = (e) => {
currentX = e.clientX - startX;
dragTab.style.transform = `translateX(${currentX}px)`;
};
document.onmouseup = () => {
document.onmousemove = null;
document.onmouseup = null;
};
};
});
</script>
</body
顺便总结一下常用的浏览器鼠标坐标获取方式:
| 坐标属性 | 含义 | 核心特点 |
|---|---|---|
clientX/clientY |
相对于浏览器视口(当前可见区域)的坐标 | 滚动页面时,值不随滚动改变 |
pageX/pageY |
相对于整个文档的坐标 | 包含滚动出去的部分,滚动时值会变化 |
screenX/screenY |
相对于电脑屏幕的坐标 | 从屏幕左上角开始计算 |
offsetX/offsetY |
相对于触发事件的元素(event.target)左上角的坐标 |
点击元素内部时,值是相对于该元素的位置 |






