element plus组件el-transfer拖拽排序功能实现
element
A Vue.js 2.0 UI Toolkit for Web
项目地址:https://gitcode.com/gh_mirrors/eleme/element
免费下载资源
·
效果图
前置说明
本功能适用于Vue3+element plus,限制左侧不能拖拽排序
实现技术
原生web API dragstart、dragenter、dragend技术;为什么不使用vuedraggable plus?因为使用过程中,右侧新生成的数据项无法拖动
代码:
THML
<template>
<el-transfer
ref="sortableRef"
v-model="rightData"
filterable
:filter-method="filterMethod"
filter-placeholder="请输入"
:data="data"
@change="transferChange"
>
<template #default="{ option }">
<div
class="transferLable"
:draggable="rightData.includes(option.key)"
@dragstart="handleDragStart(option)"
@dragenter="handleDragenter($event,option)"
@dragend="handleDrop($event)"
>
<span class="trnsferValue">{{ option.label }}</span>
<span
id="draggable"
class="sort"
>
<el-icon><Rank /></el-icon>
</span>
</div>
</template>
</el-transfer>
</template>
js
<script setup name="nurserItem">
import { ref } from 'vue'
import { Rank } from '@element-plus/icons-vue'
const data = ref([
{ key: 0, label: '11' },
{ key: 1, label: '22' },
{ key: 2, label: '33' },
{ key: 3, label: '44' },
{ key: 4, label: '55' },
{ key: 5, label: '66' }
])
const rightData = ref([])
const filterMethod = (query, item) => {
if (!query) { return true }
return item.label.includes(query)
}
// 往右侧添加时,手动添加头部
const transferChange = (_, direction, movedKeys) => {
if (direction === 'right') {
const arrList = data.value.filter(item => !movedKeys.includes(item.key))
const arrUnshift = data.value.filter(item => movedKeys.includes(item.key))
data.value = [...arrUnshift, ...arrList]
}
}
let dragTarget = null // 用于存储被拖动的目标项
let dragIndex = -1 // 被拖动项在数组中的原始索引
let targetOption = null// 拖动过程中停放目标
// 开始拖动
const handleDragStart = (option) => {
dragTarget = option
dragIndex = data.value.findIndex(item => item === option)
}
// 放置时重新排序数组
const handleDragenter = (event, option) => {
event.preventDefault()
if (!dragTarget || !option) return
targetOption = option
if (event.target.draggable) {
clearMovingDOM()
const targetIndex = data.value.findIndex(item => item.key === targetOption.key)
if (targetIndex < dragIndex) { // 往上拖拽
event.target.className = 'movingTop'
} else { // 往下拖拽
event.target.className = 'movingBottom'
}
}
}
// 鼠标放开--拖拽结束
const handleDrop = () => {
const targetIndex = data.value.findIndex(item => item.key === targetOption.key)
const newIndex = targetIndex
// 更新数组顺序
const [removed] = data.value.splice(dragIndex, 1)
data.value.splice(newIndex, 0, removed)
// 重置拖动状态
dragTarget = null
targetOption = null
dragIndex = -1
clearMovingDOM()
}
// 清除moving Class名
const clearMovingDOM = () => {
document.querySelectorAll('.movingBottom').forEach(Element => {
Element.className = 'transferLable'
})
document.querySelectorAll('.movingTop').forEach(Element => {
Element.className = 'transferLable'
})
}
</script>
CSS
<style scoped lang="less">
::v-deep(.el-transfer-panel__item).el-checkbox {
margin-right:10px;
.transferLable{
display: flex;
justify-content: space-between !important;
}
}
.el-transfer ::v-deep(.el-transfer-panel):first-child .sort{
display: none;
}
.moving{
border-bottom: 1px solid #409eff;
}
.movingTop{
border-top: 1px solid #409eff;
}
.movingBottom{
border-bottom: 1px solid #409eff;
}
</style>
备注:以上就是全部实现功能,有问题,大家可以私聊我。如有雷同,必将追究
GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:3 个月前 )
c345bb45
7 个月前
a07f3a59
* Update transition.md
* Update table.md
* Update transition.md
* Update table.md
* Update transition.md
* Update table.md
* Update table.md
* Update transition.md
* Update popover.md 7 个月前
更多推荐
已为社区贡献1条内容
所有评论(0)