vue实现tabs拖拽
效果图
dragTab.vue
<template>
<div class="yh-tabs">
<draggable :list="tabList" :group="groupName" animation="300" item-key="id" @end="dragEnd">
<template #item="{ element, index }">
<span :class="['yh-tabs-item', attrs.modelValue === element[modelKey] ? 'active' : '']"
@click="changeActive(element)">
<slot name="head" :data="{ element, index }">
<span>
{{ element[label] }}
</span>
</slot>
</span>
</template>
</draggable>
</div>
<div class="tab-pane">
<slot :item="curTab"></slot>
</div>
</template>
<script setup>
import { defineProps, useAttrs, defineEmits, computed } from 'vue'
import draggable from 'vuedraggable';
const attrs = useAttrs()
const props = defineProps({
tabList: {
type: Array,
required: true
},
modelKey: {
type: String,
required: true
},
label: {
type: String,
required: true
},
groupName: {
type: String,
required: true
}
})
const emits = defineEmits(['update:modelValue', 'changeList', 'changeActive'])
const curTab = computed(() => props.tabList.find(item => item[props.modelKey] === attrs.modelValue))
const changeActive = (element) => {
curTab.value = element
emits('update:modelValue', element[props.modelKey])
emits('changeActive', element)
}
const dragEnd = () => emits('changeList', props.tabList)
</script>
<style lang="less" scoped>
.yh-tabs {
position: relative;
box-sizing: border-box;
&::after {
content: '';
display: block;
width: 100%;
height: 2px;
background: #CCC;
position: absolute;
bottom: -7px;
left: 0;
z-index: -1;
}
.yh-tabs-item {
padding: 5px 10px;
cursor: pointer;
}
.yh-tabs-item.active {
color: #1890FF;
border-bottom: 2px solid #1890FF;
}
}
.tab-pane {
margin-top: 24px;
}
</style>
test.vue
<template>
<yhTabs v-model="active" :tabList="tabPaneList" modelKey="name" label="label" @changeList="changeList"
groupName="tabs1" @changeActive="changeActive">
<template #head="{ data: { index } }">
<span>第{{ index }}列</span>
</template>
<template #="{ item }">
<div class="yh-tab-pane">
<div class="myinfo">
{{ item }}
</div>
<div>
<yh-tabs v-model="chTab" :tabList="item.tabs" modelKey="name" label="label" groupName="tabs2">
<template #="{ item }">
{{ item }}
</template>
</yh-tabs>
</div>
</div>
</template>
</yhTabs>
</template>
<script setup>
import { ref } from 'vue'
import yhTabs from './dragTabs/index.vue'
const active = ref('1')
const chTab = ref('1-1')
const tabPaneList = ref([
{
name: '1',
label: '标签1',
tabs: [
{
name: '1-1',
label: '标签1-1'
},
{
name: '1-2',
label: '标签1-2'
}
]
},
{
name: '2',
label: '标签2',
tabs: [
{
name: '2-1',
label: '标签2-1'
},
{
name: '2-2',
label: '标签2-2'
}
]
},
{
name: '3',
label: '标签3',
tabs: [
{
name: '3-1',
label: '标签3-1'
},
{
name: '3-2',
label: '标签3-2'
}
]
},
{
name: '4',
label: '标签4',
tabs: [
{
name: '4-1',
label: '标签4-1'
},
{
name: '4-2',
label: '标签4-2'
}
]
}
])
const changeList = data => tabPaneList.value = data
const changeActive = active => {
chTab.value = active.tabs[0].name
}
</script>
<style lang="less" scoped>
.myinfo{
margin: 24px;
}
.yh-tab-pane{
margin-top: 24px;
}
</style>