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>

<think>好的,我需要帮助用户了解如何使用Vue 3编写一个列表的CRUD应用。首先,我得回忆一下Vue 3的基本概念和Composition API的用法。用户可能需要一个简单的示例,包含创建、读取、更新和删除功能。 首先,我应该确定项目结构。用户可能需要安装Vue 3,所以需要先说明如何初始化项目。使用Vite可能是个好选择,因为它快速且简单。然后,创建一个新的组件,比如TodoList.vue,用来展示列表和处理操作。 接下来,数据部分。需要使用ref或reactive来管理状态。假设是一个待办事项列表,每个事项有id、标题和状态。可能需要用到一个数组来存储这些事项,并提供添加、编辑和删除的方法。 模板部分需要展示列表,每个项目有编辑和删除按钮。对于添加和编辑,可能需要一个表单,输入框和提交按钮。在编辑时,需要将当前选中的项目数据绑定到表单,方便修改。 然后,处理用户交互。添加功能需要将新事项推入数组,编辑需要找到对应id的项并更新,删除则是过滤掉该id的项。需要确保这些操作都是响应式的,这样视图会自动更新。 样式方面,可能需要一些基本的CSS来美化界面,比如列表项的布局、按钮的样式等。不过用户可能更关注功能实现,样式可以简单处理。 最后,测试功能是否正常。添加新项,编辑现有项,删除项,确保所有操作都能正确更新视图和数据。同时,处理可能的边缘情况,比如空输入或重复id的问题。 可能还需要考虑使用组件间的通信,如果功能复杂的话,但在这个示例中,可能所有逻辑都放在一个组件里更简单。另外,是否需要后端交互?用户可能只需要前端示例,所以数据保存在内存中即可。 总结步骤:初始化项目,创建组件,设置响应式数据,编写模板和事件处理,实现CRUD方法,添加样式,测试功能。确保代码示例清晰,注释详细,方便用户理解。</think>以下是用Vue 3实现列表CRUD的完整示例(使用Composition API): ```html <!-- TodoList.vue --> <template> <div class="container"> <!-- 添加/编辑表单 --> <form @submit.prevent="handleSubmit"> <input type="text" v-model="currentItem.title" placeholder="输入事项" required /> <button type="submit"> {{ isEditing ? &#39;更新&#39; : &#39;添加&#39; }} </button> </form> <!-- 列表展示 --> <ul v-if="items.length > 0"> <li v-for="item in items" :key="item.id"> <span :class="{ completed: item.completed }"> {{ item.title }} </span> <div> <button @click="toggleStatus(item.id)">切换状态</button> <button @click="editItem(item)">编辑</button> <button @click="deleteItem(item.id)">删除</button> </div> </li> </ul> <p v-else>暂无事项,请添加</p> </div> </template> <script setup> import { ref, reactive } from &#39;vue&#39; // 响应式数据 const items = ref([]) const isEditing = ref(false) const currentItem = reactive({ id: null, title: &#39;&#39;, completed: false }) // 生成唯一ID let idCounter = 0 const generateId = () => ++idCounter // 提交处理 const handleSubmit = () => { if (isEditing.value) { // 更新现有项 const index = items.value.findIndex(item => item.id === currentItem.id) if (index !== -1) { items.value[index] = { ...currentItem } } isEditing.value = false } else { // 添加新项 items.value.push({ ...currentItem, id: generateId() }) } resetForm() } // 编辑处理 const editItem = (item) => { Object.assign(currentItem, item) isEditing.value = true } // 删除处理 const deleteItem = (id) => { items.value = items.value.filter(item => item.id !== id) } // 切换完成状态 const toggleStatus = (id) => { const item = items.value.find(item => item.id === id) if (item) item.completed = !item.completed } // 重置表单 const resetForm = () => { currentItem.id = null currentItem.title = &#39;&#39; currentItem.completed = false } </script> <style scoped> .container { max-width: 600px; margin: 2rem auto; padding: 1rem; } form { display: flex; gap: 0.5rem; margin-bottom: 1rem; } input { flex: 1; padding: 0.5rem; } button { padding: 0.5rem 1rem; cursor: pointer; } ul { list-style: none; padding: 0; } li { display: flex; justify-content: space-between; align-items: center; padding: 0.5rem; margin: 0.5rem 0; border: 1px solid #ddd; border-radius: 4px; } .completed { text-decoration: line-through; color: #666; } </style> ``` 主要功能说明: 1. **响应式数据管理**: - 使用`ref`和`reactive`管理状态 - `items`存储所有列表项 - `currentItem`处理当前编辑/新增的项 2. **核心CRUD操作**: - **Create**:通过表单提交添加新事项 - **Read**:使用`v-for`展示列表项 - **Update**:通过编辑按钮触发,填充表单进行修改 - **Delete**:通过ID过滤删除指定项 3. **附加功能**: - 状态切换(完成/未完成) - 表单验证(必填项) - 空状态提示 - 自动生成唯一ID 4. **代码结构特点**: - 使用Composition API组织逻辑 - 组件化开发 - 响应式更新DOM - 样式隔离(scoped CSS) 使用步骤: 1. 使用Vite创建Vue项目 2. 创建`TodoList.vue`组件 3. 在父组件中导入使用 ```bash # 创建Vue项目 npm create vue@latest ``` 优势: - 响应式数据绑定 - 清晰的逻辑分离 - 可维护的代码结构 - 内置状态管理 - 高效的DOM更新 扩展建议: 1. 添加本地存储持久化 2. 增加表单验证提示 3. 实现服务端通信 4. 添加分类过滤功能 5. 实现拖拽排序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

柳晓黑胡椒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值