🚀 个人简介:某大型测绘遥感企业资深Webgis开发工程师,软件设计师(中级)、优快云优质创作者
💟 作 者:柳晓黑胡椒❣️
📝 专 栏:vue实践
🌈 若有帮助,还请关注 ➕ 点赞➕收藏,不行的话我再努努力💪💪💪
需求背景
需要封装一个可通过拖拽实现的标签排序的组件
- 标签列表进行crud操作
- 鼠标拖拽改变标签的排序
- 支持多种数据
解决思路
1.基本功:使用HTML5
c的拖拽
系列api
实现效果
vue3 实现标签拖拽排序 + curd
组件文档
Attributes
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
modelValue | 绑定值 | [] | — | — |
newVal | 新增的数据 | string | — | — |
minWidth | 最小宽度 | number | — | — |
isDrag | 拉伸区域操作padding | number | — | — |
Events
事件名称 | 说明 | 回调参数 |
---|---|---|
numChange | 标签数量变化的回调 | — |
index.vue
/**
* @author: liuk
* @date: 2025-01-16
* @describe:拖拽排序
*/
<template>
<div class="dragSort-wrap">
<el-tag v-for="(item,index) in list" class="account-item" :draggable="true" @dragenter="dragenter(index)"
@dragend="dragend(item,index)" :style="{width:minWidth,margin: '0 5px 5px 0'}" closable
@click="editFn(item,index)"
@close="delFn(index)">
<span style="margin-right: 10px;color: #4faecc">{{ index + 1 }}</span>
<el-input size="small" v-if="editIndex === index" v-model.trim="editVal"
@change="editValChang($event,index)" autofocus/>
<span v-else>{{ item }}</span>
</el-tag>
<el-tag type="success" :style="{width:minWidth,margin: '0 5px 5px 0'}" @click="addFn"> +</el-tag>
</div>
</template>
<script lang="ts" setup>
import {computed, reactive, toRefs, withDefaults} from "vue"
import {ElMessage} from "element-plus";
// Props
interface Props {
modelValue: [] //必传
newVal: number | string//必传
minWidth: string//必传
isDrag?: boolean
}
const props = withDefaults(defineProps<Props>(), {
isDrag: true,
})
// Emits
const emits = defineEmits<{
(e: "update:modelValue", value: []): void
(e: "numChange"): void
}>()
const list = computed({
get() {
return props.modelValue;
},
set(val) {
emits('update:modelValue', val);
},
})
const model = reactive({
moveIndex: 0, // 当前
editVal: "",
editIndex: "",
})
const {editVal, editIndex} = toRefs(model)
const dragenter = (index) => {
model.editVal = ""
model.editIndex = ""
model.moveIndex = index
}
const dragend = (val, index) => {
if (!props.isDrag) return
list.value.splice(index, 1)
list.value.splice(model.moveIndex, 0, val)
}
const editFn = (val, index) => {
model.editVal = val
model.editIndex = index
}
const editValChang = (val, index) => {
try {
JSON.parse(val)
} catch (e) {
ElMessage.warning("请填写有效数据")
return
}
list.value[index] = val
list.value = list.value.sort((a, b) => JSON.parse(a).X - JSON.parse(b).X)
model.editVal = ""
model.editIndex = ""
}
const delFn = (index) => {
list.value.splice(index, 1)
emits("numChange")
}
const addFn = () => {
list.value.push(props.newVal)
emits("numChange")
}
</script>
<style lang="scss" scoped>
.dragSort-wrap {
display: flex;
flex-wrap: wrap;
:deep(.el-input) {
width: var(--width - 100);
--el-fill-color-blank: transparent;
--el-border-color: transparent;
--el-text-color-regular: #000;
}
}
</style>