vue3+ant-design-vue4.x+sortablejs 实现可拖拽行表格

vue3+ant-design-vue4.x+sortablejs 实现可拖拽行表格

sortablejs网址:sortablejs.com/

npm安装 npm install sortablejs --save

js 复制代码
<template>
  <div class="draggable-table-wrapper">
    <a-table
      ref="tableRef"
      :columns="columns"
      :data-source="tableData"
      row-key="id"
      :pagination="false"
      class="draggable-table"
    >
      <!-- 可根据需要添加操作列 -->
      <template #action="{ record }">
        <a-button size="small" type="text" @click="handleView(record)"> 查看 </a-button>
      </template>
    </a-table>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick, watch } from 'vue'
import { Table, Card, Button, message } from 'ant-design-vue'
import Sortable from 'sortablejs'

// 表格数据
const tableData = ref([
  { id: '1', name: '张三', age: 28, department: '产品部', email: 'zhangsan@example.com' },
  { id: '2', name: '李四', age: 32, department: '开发部', email: 'lisi@example.com' },
  { id: '3', name: '王五', age: 25, department: '设计部', email: 'wangwu@example.com' },
  { id: '4', name: '赵六', age: 35, department: '测试部', email: 'zhaoliu@example.com' },
  { id: '5', name: '钱七', age: 29, department: '市场部', email: 'qianqi@example.com' },
  { id: '6', name: '孙八', age: 31, department: '开发部', email: 'sunba@example.com' },
  { id: '7', name: '周九', age: 27, department: '产品部', email: 'zhoujiu@example.com' }
])

// 表格列定义
const columns = [
  {
    title: '姓名',
    dataIndex: 'name',
    key: 'name',
    width: 120
  },
  {
    title: '年龄',
    dataIndex: 'age',
    key: 'age',
    width: 80
  },
  {
    title: '部门',
    dataIndex: 'department',
    key: 'department',
    width: 120
  },
  {
    title: '邮箱',
    dataIndex: 'email',
    key: 'email'
  },
  {
    title: '操作',
    key: 'action',
    width: 100,
    slots: { customRender: 'action' }
  }
]

// 分页配置
const pagination = ref({
  pageSize: 5,
  showSizeChanger: true,
  pageSizeOptions: ['5', '10', '20'],
  showTotal: (total) => `共 ${total} 条记录`
})

// 表格引用
const tableRef = ref()
// 最后更新时间
const lastUpdated = ref('')
// 排序实例
let sortableInstance = null

// 初始化拖拽功能
const initSortable = () => {
  // 确保先销毁已存在的实例
  if (sortableInstance) {
    sortableInstance.destroy()
  }

  nextTick(() => {
    // 获取表格的tbody元素
    const tableBody = tableRef.value.$el.querySelector('.ant-table-tbody')
    console.log(tableBody, tableRef.value, tableRef.value.$el, tableRef.value.table, 'tableBody')
    if (tableBody) {
      // 初始化Sortable
      sortableInstance = new Sortable(tableBody, {
        animation: 150, // 动画时间
        delay: 100, // 延迟开始拖拽,防止误操作
        delayOnTouchOnly: true,
        ghostClass: 'sortable-ghost', // 拖拽时的占位元素样式
        chosenClass: 'sortable-chosen', // 选中元素的样式
        dragClass: 'sortable-drag', // 拖拽元素的样式

        onStart: () => {},

        onEnd: (evt) => {
          const { oldIndex, newIndex } = evt

          // 处理拖拽结束后的逻辑
          if (oldIndex !== newIndex && oldIndex !== undefined && newIndex !== undefined) {
            // 复制原数据并调整顺序
            const newData = [...tableData.value]
            const [movedItem] = newData.splice(oldIndex, 1)
            newData.splice(newIndex, 0, movedItem)

            // 更新数据
            tableData.value = newData

            // 更新最后操作时间
            lastUpdated.value = new Date().toLocaleString()

            // 这里可以添加保存到服务器的逻辑
            // saveNewOrder(newData.map(item => item.id));
          }
        }
      })
    }
  })
}

// 监听分页变化,重新初始化拖拽
watch(
  () => pagination.value.current,
  () => {
    initSortable()
  }
)

watch(
  () => pagination.value.pageSize,
  () => {
    initSortable()
  }
)

// 组件挂载时初始化拖拽
onMounted(() => {
  initSortable()
})

// 查看详情
const handleView = (record) => {
  message.info(`查看 ${record.name} 的详情`)
  // 这里可以添加查看详情的逻辑
}
</script>

<style scoped>
:deep(.ant-table-tbody > tr) {
  &:hover {
    td {
      cursor: move;
      &:first-child {
        &::before {
          content: '';
          position: absolute;
          left: 0;
          top: 0;
          width: 20px;
          height: 56px;
          background: url('@/pc/assets/images/tableDrag.svg');
          background-size: 100% 100%;
        }
      }
    }
  }
}
</style>
相关推荐
Laurence22 分钟前
从零到一构建 C++ 项目(IDE / 命令行双轨实现)
前端·c++·ide
雯0609~32 分钟前
hiprint-官网vue完整版本+实现客户端配置+可实现直接打印(在html版本增加了条形码、二维码拖拽等)
前端·javascript·vue.js
GISer_Jing34 分钟前
构建高性能Markdown引擎开发计划
前端·aigc·ai编程
CHU7290351 小时前
生鲜商城小程序前端功能版块:适配生鲜采购核心需求
前端·小程序
huangyiyi666661 小时前
Vue + TS 项目文件结构
前端·javascript·vue.js
0思必得01 小时前
[Web自动化] Selenium处理Cookie
前端·爬虫·python·selenium·自动化
徐同保2 小时前
react-markdown使用
前端·react.js·前端框架
2601_949857432 小时前
Flutter for OpenHarmony Web开发助手App实战:CSS参考
前端·css·flutter
无法长大2 小时前
如何判断项目需不需要用、能不能用Tailwind CSS
前端·css·vue.js·elementui·vue3·tailwind css
橙露2 小时前
移动端前端适配:Rem、VW/VH 与媒体查询的综合应用指南
前端·媒体