vue3 实现标签拖拽排序 + curd

🚀 个人简介:某大型测绘遥感企业资深Webgis开发工程师,软件设计师(中级)、优快云优质创作者
💟 作 者:柳晓黑胡椒❣️
📝 专 栏:vue实践
🌈 若有帮助,还请关注点赞收藏,不行的话我再努努力💪💪💪

需求背景

需要封装一个可通过拖拽实现的标签排序的组件

  1. 标签列表进行crud操作
  2. 鼠标拖拽改变标签的排序
  3. 支持多种数据

解决思路

1.基本功:使用HTML5c的拖拽系列api

实现效果

vue3 实现标签拖拽排序 + curd

组件文档

Attributes

参数说明类型可选值默认值
modelValue绑定值[]
newVal新增的数据string
minWidth最小宽度number
isDrag拉伸区域操作paddingnumber

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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柳晓黑胡椒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值