前言:目前市面上有很多实现拖拽排序功能的插件和方法,本节不过多累述,只讲一种:vue的v-dragging内置组件
效果图:
主图:
拖拽中的图:
1. 安装
npm install awe-dnd --save
2. 在 main.js 文件中引入
import VueDND from 'awe-dnd'
Vue.use(VueDND)
3. v-dragging 调用
v-dragging="{ list: tabList, item: item, group: 'item' }"
4. v-dragging 参数
5. 重构带删除的Tabs组件
因为element的el-tabs组件不支持拖拽排序功能,并且该标签封装了多层嵌套div,不利于拖动排序的时候操作内部的DOM节点,所以首先重写一个带删除的Tab组件
- 重构DOM
-
<span class="all-app" :class="{tabActiveAll:activeAllFlag}" @click="changeTab">{{$t('apps.all_app')}}</span> <div class=""tab-container> <div class="tab-box" v-for="(item, index) in categoryList" v-dragging="{ list: categoryList, item: item, group: 'item' }" :key="item.id" :class="{tabActive:currentIndex === index}" @click="changeTab(item, index)"> // Tab标签超出长度显示el-tooltip提示 placement为提示显示位置 disabled为提示是否显示(本案例是文字长度超过了7个才显示) <el-tooltip class="item" effect="dark" :content="item.name" placement="right" :disabled="item.name.length < 7"> <div class="tab-pane"> {{item.name}}</div> </el-tooltip> // 删除图标 <i class="el-icon-close" @click.stop="removeTab(item.id)"></i> </div> </div>
- Data中定义数据
<script>
export default {
data() {
return {
categoryList: [], // Tab 数组
tabActive: '', // 当前点击的Tab
currentIndex: 0, // 当前点击的Tab索引
activeAllFlag: true // 是否选中全部应用
}
}
}
</script>
6. methods方法中使用
Tab 自定义删除功能
// 点击Tab
changeTab(tab, index) {
this.currentTabId = tab.id
// 动态添加tabActive样式,模拟element Tab被选中,呈现下边线样式
this.currentIndex = index
// index为undefined时, 为点击的是全部应用
if (index === undefined) {
this.currentTabId = ''、
// 动态添加tabActiveAll类名,模拟element Tab被选中,呈现下边线样式
this.activeAllFlag = true
} else {
// 未点击全部应用,则动态移除当前样式
this.activeAllFlag = false
}
},
// 删除Tab标签
removeTab(targetId) {
let data = []
let currentId = ''
// 当前删除Tab ID
this.categoryList.forEach(item => {
if (item.id === targetId) currentId = item.id
})
// 调用删除接口,时时同步数据
delTab(currentId).then(res => {
this.$message.success('删除成功')
})
}
Tab 拖拽排序功能
mounted() {
this.$dragging.$on('dragend', () => {
this.orderIds = []
this.categoryList.forEach((item) => {
this.orderIds.push(item.id)
})
// 推荐此种前后端交互:
此接口交互,是将拖拽后重组的ID集合,传给接口,时时更新数据,和v-dragging 数据处理结构保存一致
changeOrder(this.orderIds).then((res) => {
this.$message.success('拖拽排序成功')
})
})
}
7. 模拟element Tab 标签样式
<style lang="scss" scoped>
.all-app {
height: 48px;
cursor: pointer;
color: #1F2226;
font-size: 16px;
}
.tabActiveAll {
height: 47px;
color: #526ECC;
border-bottom: 2px solid #526ECC;
}
.tabActive {
height: 48px;
border-bottom: 2px solid #526ECC;
.tab-pane {
color: #526ECC!important;
}
.el-icon-close {
color: #526ECC;
}
}
.tab-container {
display: flex;
height: 50px;
line-height: 50px;
.tab-box {
max-width: 140px;
display: flex;
margin-left: 30px;
cursor: pointer;
.tab-pane {
max-width: 97px;
height: 48px;
cursor: pointer;
color: #1F2226;
font-size: 16px;
text-align: center;
margin-right: 7px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.el-icon-close {
color: #1F2226;
line-height: 51px;
}
}
}
</style>