antdvue-table的表格并未直接提供拖拽方法,需要在使用的时候去自定义a-table的customRow方法,这里仅以antdvue的3.x版本为示例

直接上代码

<template>
  <a-table :dataSource="dataSource" :columns="columns" :customRow="customRow" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
const dataSource = ref([
  {
    key: '1',
    name: '胡彦斌',
    age: 32,
    address: '西湖区湖底公园1号',
    serialNumber: 1,
    isModified: '0',
  },
  {
    key: '2',
    name: '胡彦祖',
    age: 42,
    address: '西湖区湖底公园1号',
    serialNumber: 2,
    isModified: '0',
  },
])

const columns = ref([
  {
    title: '姓名',
    dataIndex: 'name',
    key: 'name',
  },
  {
    title: '年龄',
    dataIndex: 'age',
    key: 'age',
  },
  {
    title: '住址',
    dataIndex: 'address',
    key: 'address',
  },
])

/**拖拽起始行 */
const sourceRecord = ref<any>({})
/**拖拽目标行 */
const targetRecord = ref<any>({})
/**拖拽起始索引 */
let oldIndex: number | null = null
/**拖拽目标索引 */
let newIndex: number | null = null

const customRow = (record: any, index: number) => {
  return {
    style: {
      cursor: 'pointer',
    },
    // 鼠标移入
    onMouseenter: (event: MouseEvent) => {
      // 兼容IE
      const ev = event || window.event
      const target = ev.target as HTMLElement
      target.draggable = true
    },
    // 开始拖拽
    onDragstart: (event: Event) => {
      // 兼容IE
      const ev = event || window.event
      ev.stopPropagation()
      // 得到源目标数据
      sourceRecord.value = record
      oldIndex = index
    },
    // 拖动元素经过的元素
    onDragover: (event: DragEvent) => {
      // 兼容 IE
      const ev = event || window.event
      // 阻止默认行为
      ev.preventDefault()
      ev.dataTransfer!.dropEffect = 'move' // 可以去掉拖动时那个+号
      newIndex = index
    },
    // 鼠标松开
    onDrop: (event: Event) => {
      // 兼容IE
      const ev = event || window.event
      // 阻止冒泡
      ev.stopPropagation()
      // 得到目标数据
      targetRecord.value = record
      // 将源数据插入目标数据前面
      newIndex = index

      if (newIndex === oldIndex) return

      // 如果从1拖到10,那么1-10之间的isModified都要改为1,或者从10拖到1
      const startIndex = newIndex > oldIndex! ? oldIndex : newIndex
      const endIndex = newIndex > oldIndex! ? newIndex : oldIndex
      for (let i = startIndex; i! <= endIndex!; i!++) {
        dataSource[i!]['isModified'] = '1'
      }

      dataSource[oldIndex!].serialNumber = newIndex + 1
      dataSource[newIndex!].serialNumber = oldIndex! + 1
      dataSource.value.splice(oldIndex!, 1)
      dataSource.value.splice(newIndex, 0, sourceRecord.value)
    },
  }
}
</script>

如果说多个组件/表格要使用,我们可以把这段代码抽取到一个hook里,代码如下


// useDragTable.ts

import { ref } from 'vue'

type RecordType = anyObject & { serialNumber: number; isModified: string }

/**
 * @method 表格行拖拽
 * @param dataSource 数据源
 */
export default function useDragTable<T extends RecordType = RecordType>(dataSource: T[]) {
  /**拖拽起始行 */
  const sourceRecord = ref<Partial<T>>({})
  /**拖拽目标行 */
  const targetRecord = ref<Partial<T>>({})
  /**拖拽起始索引 */
  let oldIndex: number | null = null
  /**拖拽目标索引 */
  let newIndex: number | null = null

  /**
   * @method 自定义拖拽行
   * @param record 当前行数据
   * @param index 当前行索引
   */
  function customRow(record: T, index: number) {
    return {
      style: {
        cursor: 'pointer',
      },
      // 鼠标移入
      onMouseenter: (event: MouseEvent) => {
        // 兼容IE
        const ev = event || window.event
        const target = ev.target as HTMLElement
        target.draggable = true
      },
      // 开始拖拽
      onDragstart: (event: Event) => {
        // 兼容IE
        const ev = event || window.event
        ev.stopPropagation()
        // 得到源目标数据
        sourceRecord.value = record
        oldIndex = index
      },
      // 拖动元素经过的元素
      onDragover: (event: DragEvent) => {
        // 兼容 IE
        const ev = event || window.event
        // 阻止默认行为
        ev.preventDefault()
        ev.dataTransfer!.dropEffect = 'move' // 可以去掉拖动时那个+号
        newIndex = index
      },
      // 鼠标松开
      onDrop: (event: Event) => {
        // 兼容IE
        const ev = event || window.event
        // 阻止冒泡
        ev.stopPropagation()
        // 得到目标数据
        targetRecord.value = record
        // 将源数据插入目标数据前面
        newIndex = index

        if (newIndex === oldIndex) return

        // 如果从1拖到10,那么1-10之间的isModified都要改为1,或者从10拖到1
        const startIndex = newIndex > oldIndex! ? oldIndex : newIndex
        const endIndex = newIndex > oldIndex! ? newIndex : oldIndex
        for (let i = startIndex; i! <= endIndex!; i!++) {
          dataSource[i!]['isModified'] = '1'
        }

        dataSource[oldIndex!].serialNumber = newIndex + 1
        dataSource[newIndex!].serialNumber = oldIndex! + 1
        dataSource.splice(oldIndex!, 1)
        dataSource.splice(newIndex, 0, sourceRecord.value)
      },
    }
  }

  return {
    sourceRecord,
    targetRecord,
    oldIndex,
    newIndex,
    customRow,
  }
}


// home.vue

<template>
  <a-table :dataSource="dataSource" :columns="columns" :customRow="customRow" />
</template>


<script setup lang="ts">
import { ref } from 'vue'
import useDragTable from '@/hooks/useDragTable'

type DataSourceType = anyObject & { serialNumber: number; isModified: string }

const dataSource = ref<DataSourceType[]>([
  {
    key: '1',
    name: '胡彦斌',
    age: 32,
    address: '西湖区湖底公园1号',
    serialNumber: 1,
    isModified: '0',
  },
  {
    key: '2',
    name: '胡彦祖',
    age: 42,
    address: '西湖区湖底公园1号',
    serialNumber: 2,
    isModified: '0',
  },
])

const columns = ref([
  {
    title: '姓名',
    dataIndex: 'name',
    key: 'name',
  },
  {
    title: '年龄',
    dataIndex: 'age',
    key: 'age',
  },
  {
    title: '住址',
    dataIndex: 'address',
    key: 'address',
  },
])

const { customRow } = useDragTable<DataSourceType>(dataSource.value)
</script>

GitHub 加速计划 / vu / vue
207.54 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 4 个月前
e428d891 Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐