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>
相关推荐
杰克尼9 分钟前
vue_day04
前端·javascript·vue.js
明远湖之鱼40 分钟前
浅入理解跨端渲染:从零实现 React DSL 跨端渲染机制
前端·react native·react.js
悟忧1 小时前
规避ProseMirror React渲染差异带来的BUG
前端
小皮虾1 小时前
小程序云开发有类似 uniCloud 云对象的方案吗?有的兄弟,有的!
前端·javascript·小程序·云开发
Android疑难杂症1 小时前
鸿蒙Notification Kit通知服务开发快速指南
android·前端·harmonyos
T___T1 小时前
全方位解释 JavaScript 执行机制(从底层到实战)
前端·面试
阳懿2 小时前
meta-llama-3-8B下载失败解决。
前端·javascript·html
Qinana2 小时前
🌊 深入理解 CSS:从选择器到层叠的艺术
前端·css·程序员
IT_陈寒2 小时前
Python 3.12新特性实测:10个让你的代码提速30%的隐藏技巧 🚀
前端·人工智能·后端
闲人编程2 小时前
从零开发一个简单的Web爬虫(使用Requests和BeautifulSoup)
前端·爬虫·beautifulsoup·bs4·web·request·codecapsule